Hindari loop dalam cangkang.
Jika Anda ingin melakukan aritmatika, gunakan awkatau bc:
awk '
BEGIN{
for (i = 4.00; i < 5.42; i+ = 0.02)
print i
}'
Atau
bc << EOF
for (i = 4.00; i < 5.42; i += 0.02) i
EOF
Perhatikan bahwa awk(bertentangan dengan bc) bekerja dengan doublerepresentasi nomor floating point prosesor Anda (kemungkinan tipe IEEE 754 ). Akibatnya, karena angka-angka itu adalah perkiraan biner dari angka desimal itu, Anda mungkin memiliki beberapa kejutan:
$ gawk 'BEGIN{for (i=0; i<=0.3; i+=0.1) print i}'
0
0.1
0.2
Jika Anda menambahkan, OFMT="%.17g"Anda dapat melihat alasan hilangnya 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 tidak presisi sewenang-wenang sehingga tidak memiliki masalah seperti ini.
Perhatikan bahwa secara default (kecuali jika Anda memodifikasi format output dengan OFMTatau menggunakan printfdengan spesifikasi format eksplisit), awkdigunakan %.6guntuk menampilkan angka floating point, jadi akan beralih ke 1e6 dan di atasnya untuk angka floating point di atas 1.000.000 dan memotong bagian fraksional untuk angka tinggi (100000.02 akan ditampilkan sebagai 100000).
Jika Anda benar-benar perlu menggunakan shell loop, karena misalnya Anda ingin menjalankan perintah khusus untuk setiap iterasi dari loop itu, baik menggunakan shell dengan dukungan aritmatika floating point seperti zsh, yashatau ksh93atau menghasilkan daftar nilai dengan satu perintah seperti di atas (atau seqjika tersedia) dan lewati outputnya.
Suka:
unset -v IFS # configure split+glob for default word splitting
for i in $(seq 4 0.02 5.42); do
something with "$i"
done
Atau:
seq 4 0.02 5.42 | while IFS= read i; do
something with "$i"
done
kecuali Anda menekan batas angka floating point prosesor Anda, seqmenangani kesalahan yang ditimbulkan oleh pendekatan floating point lebih anggun daripada awkversi di atas.
Jika Anda tidak memiliki seq(perintah GNU), Anda dapat membuat yang lebih dapat diandalkan sebagai fungsi seperti:
seq() { # args: first increment last
bc << EOF
for (i = $1; i <= $3; i += $2) i
EOF
}
Itu akan bekerja lebih baik untuk hal-hal seperti seq 100000000001 0.000000001 100000000001.000000005. Namun perlu dicatat bahwa memiliki angka dengan presisi tinggi yang sewenang-wenang tidak akan banyak membantu jika kita akan meneruskannya ke perintah yang tidak mendukungnya.