Tránh các vòng trong vỏ.
Nếu bạn muốn làm số học, hãy sử dụng awk
hoặc bc
:
awk '
BEGIN{
for (i = 4.00; i < 5.42; i+ = 0.02)
print i
}'
Hoặc là
bc << EOF
for (i = 4.00; i < 5.42; i += 0.02) i
EOF
Lưu ý rằng awk
(trái với bc
) hoạt động với double
biểu diễn số dấu phẩy động của bộ xử lý của bạn (có thể là loại IEEE 754 ). Kết quả là, vì những số đó là xấp xỉ nhị phân của các số thập phân đó, bạn có thể có một số điều ngạc nhiên:
$ gawk 'BEGIN{for (i=0; i<=0.3; i+=0.1) print i}'
0
0.1
0.2
Nếu bạn thêm một, OFMT="%.17g"
bạn có thể thấy lý do mất tích 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
không chính xác tùy ý vì vậy không có loại vấn đề này.
Lưu ý rằng theo mặc định (trừ khi bạn sửa đổi định dạng đầu ra bằng OFMT
hoặc sử dụng printf
với thông số định dạng rõ ràng), awk
sử dụng %.6g
để hiển thị số dấu phẩy động, do đó, sẽ chuyển sang 1e6 trở lên cho các số dấu phẩy động trên 1.000.000 và cắt bớt phần phân số cho số cao (100000.02 sẽ được hiển thị là 100000).
Nếu bạn thực sự cần phải sử dụng một vòng lặp vỏ, vì ví dụ bạn muốn chạy các lệnh cụ thể cho mỗi lần lặp của vòng lặp đó, hoặc sử dụng một vỏ với dấu chấm động hỗ trợ số học như zsh
, yash
hoặc ksh93
hoặc tạo danh sách các giá trị với một lệnh như trên (hoặc seq
nếu có) và lặp qua đầu ra của nó.
Giống:
unset -v IFS # configure split+glob for default word splitting
for i in $(seq 4 0.02 5.42); do
something with "$i"
done
Hoặc là:
seq 4 0.02 5.42 | while IFS= read i; do
something with "$i"
done
trừ khi bạn đẩy các giới hạn của số dấu phẩy động của bộ xử lý, seq
xử lý các lỗi phát sinh bằng cách xấp xỉ dấu phẩy động một cách duyên dáng hơn awk
phiên bản trên.
Nếu bạn không có seq
(lệnh GNU), bạn có thể tạo một hàm đáng tin cậy hơn như một hàm như:
seq() { # args: first increment last
bc << EOF
for (i = $1; i <= $3; i += $2) i
EOF
}
Điều đó sẽ làm việc tốt hơn cho những thứ như seq 100000000001 0.000000001 100000000001.000000005
. Tuy nhiên, xin lưu ý rằng việc có các số với độ chính xác cao tùy ý sẽ không giúp ích nhiều nếu chúng ta chuyển chúng cho các lệnh không hỗ trợ chúng.