หลีกเลี่ยงการวนซ้ำในเปลือกหอย
หากคุณต้องการทำเลขคณิตให้ใช้awk
หรือbc
:
awk '
BEGIN{
for (i = 4.00; i < 5.42; i+ = 0.02)
print i
}'
หรือ
bc << EOF
for (i = 4.00; i < 5.42; i += 0.02) i
EOF
โปรดทราบว่าawk
(ตรงกันข้ามbc
) ทำงานร่วมกับการdouble
แสดงหมายเลขลอยตัวโปรเซสเซอร์ของคุณ(น่าจะเป็นประเภทIEEE 754 ) ด้วยเหตุนี้เนื่องจากตัวเลขเหล่านั้นเป็นการประมาณแบบไบนารีของตัวเลขทศนิยมเหล่านั้นคุณอาจประหลาดใจ:
$ gawk 'BEGIN{for (i=0; i<=0.3; i+=0.1) print i}'
0
0.1
0.2
หากคุณเพิ่มOFMT="%.17g"
คุณจะเห็นเหตุผลของการหายไป0.3
:
$ gawk 'BEGIN{OFMT="%.17g"; for (i=0; i<=0.5; i+=0.1) print i}'
0
0.10000000000000001
0.20000000000000001
0.30000000000000004
0.40000000000000002
0.5
bc
ความแม่นยำตามอำเภอใจจึงไม่มีปัญหาเช่นนี้
โปรดทราบว่าโดยค่าเริ่มต้น (เว้นแต่คุณจะปรับเปลี่ยนรูปแบบผลลัพธ์ด้วยOFMT
หรือใช้printf
กับข้อกำหนดรูปแบบที่ชัดเจน) awk
ใช้%.6g
สำหรับการแสดงหมายเลขจุดลอยตัวดังนั้นจะเปลี่ยนเป็น 1e6 และสูงกว่าสำหรับจำนวนจุดลอยตัวเหนือ 1,000,000 และตัดส่วนเศษส่วนสำหรับตัวเลขสูง (100000.02 จะแสดงเป็น 100,000)
หากคุณไม่ต้องการจริงๆที่จะใช้ห่วงเปลือกเพราะเช่นคุณต้องการที่จะเรียกใช้คำสั่งที่เฉพาะเจาะจงสำหรับการย้ำห่วงว่าแต่ละอย่างใดอย่างหนึ่งใช้เปลือกที่มีจุดลอยสนับสนุนทางคณิตศาสตร์เช่นzsh
, yash
หรือksh93
หรือสร้างรายการของค่ากับหนึ่งในคำสั่งดังกล่าวข้างต้น (หรือseq
ถ้ามี) และวนลูปมากกว่าเอาท์พุท
ชอบ:
unset -v IFS # configure split+glob for default word splitting
for i in $(seq 4 0.02 5.42); do
something with "$i"
done
หรือ:
seq 4 0.02 5.42 | while IFS= read i; do
something with "$i"
done
หากคุณไม่ จำกัด จำนวนจุดลอยตัวโปรเซสเซอร์ของคุณให้seq
จัดการข้อผิดพลาดที่เกิดขึ้นจากการประมาณจุดลอยตัวอย่างนุ่มนวลกว่าawk
รุ่นที่กล่าวมาข้างต้น
หากคุณไม่มีseq
(คำสั่ง GNU) คุณสามารถสร้างสิ่งที่เชื่อถือได้มากขึ้นเป็นฟังก์ชั่นเช่น:
seq() { # args: first increment last
bc << EOF
for (i = $1; i <= $3; i += $2) i
EOF
}
seq 100000000001 0.000000001 100000000001.000000005
ที่จะทำงานได้ดีขึ้นสำหรับสิ่งที่ต้องการ โปรดทราบว่าการมีตัวเลขที่มีความแม่นยำสูงโดยพลการจะไม่ช่วยอะไรมากหากเราจะส่งต่อไปยังคำสั่งที่ไม่สนับสนุน