我在bash中使用awk进行某些处理和计算,并发现比较包含数字的2个变量的减法结果并不总是有效。对于某些情况,似乎AWK在减去两个变量后留下了一些非常小的数字(大小为e-15)
我制作了一个示例代码来演示这个(compare.sh),
#!/bin/bash
run_compare() {
awk ' BEGIN {
a = 4.5
#a = 3.75
b = 0.15
match_a = 3
# // print start values and heading //
printf ("\nStart value: %s\n", a)
printf ("Substract value: %s\n", b)
printf ("\n\033[4m A: B: C: is C <= %+s?\033[0m\n", match_a)
# // Loop and substract A with B //
for(i=0;i<26;i++) {
printf ("%+4s - %+4s = ", a, b)
a = a - b
printf ("%+6s", a)
if ( a <= match_a ) {
printf (" YES\n")
} else {
printf (" NO\n")
}
}
}'
}
run_compare
此脚本的输出将为
$ ./compare.sh
Start value: 4.5
Substract value: 0.15
A: B: C: is C <= 3?
4.5 - 0.15 = 4.35 NO
4.35 - 0.15 = 4.2 NO
4.2 - 0.15 = 4.05 NO
4.05 - 0.15 = 3.9 NO
3.9 - 0.15 = 3.75 NO
3.75 - 0.15 = 3.6 NO
3.6 - 0.15 = 3.45 NO
3.45 - 0.15 = 3.3 NO
3.3 - 0.15 = 3.15 NO
3.15 - 0.15 = 3 YES
3 - 0.15 = 2.85 YES
2.85 - 0.15 = 2.7 YES
2.7 - 0.15 = 2.55 YES
2.55 - 0.15 = 2.4 YES
2.4 - 0.15 = 2.25 YES
2.25 - 0.15 = 2.1 YES
2.1 - 0.15 = 1.95 YES
1.95 - 0.15 = 1.8 YES
1.8 - 0.15 = 1.65 YES
1.65 - 0.15 = 1.5 YES
1.5 - 0.15 = 1.35 YES
1.35 - 0.15 = 1.2 YES
1.2 - 0.15 = 1.05 YES
1.05 - 0.15 = 0.9 YES
0.9 - 0.15 = 0.75 YES
0.75 - 0.15 = 0.6 YES
这一切都很好但是,如果我将值(a)更改为示例3.75而不是4.5,则会发生奇怪的事情,
$ ./compare.sh
Start value: 3.75
Substract value: 0.15
A: B: C: is C <= 3?
3.75 - 0.15 = 3.6 NO
3.6 - 0.15 = 3.45 NO
3.45 - 0.15 = 3.3 NO
3.3 - 0.15 = 3.15 NO
3.15 - 0.15 = 3 NO # // Incorrect: This should be YES //
3 - 0.15 = 2.85 YES
2.85 - 0.15 = 2.7 YES
2.7 - 0.15 = 2.55 YES
2.55 - 0.15 = 2.4 YES
2.4 - 0.15 = 2.25 YES
2.25 - 0.15 = 2.1 YES
2.1 - 0.15 = 1.95 YES
1.95 - 0.15 = 1.8 YES
1.8 - 0.15 = 1.65 YES
1.65 - 0.15 = 1.5 YES
1.5 - 0.15 = 1.35 YES
1.35 - 0.15 = 1.2 YES
1.2 - 0.15 = 1.05 YES
1.05 - 0.15 = 0.9 YES
0.9 - 0.15 = 0.75 YES
0.75 - 0.15 = 0.6 YES
0.6 - 0.15 = 0.45 YES
0.45 - 0.15 = 0.3 YES
0.3 - 0.15 = 0.15 YES
0.15 - 0.15 = 1.4988e-15 YES # // Incorrect: Should be 0 //
1.4988e-15 - 0.15 = -0.15 YES
有没有人知道为什么会这样,如果有解决方法或者我做错了什么?我试图搜索,但没有找到解释这个特殊或类似案例的任何内容。
BR /奥拉
答案 0 :(得分:0)
使用整数而不是浮点计算:
....
a = int(a * 100)
b = int(b * 100)
match_a = int(match_a * 100)
# // Loop and substract A with B //
for(i=0;i<26;i++) {
printf ("%+4s - %+4s = ", a/100, b/100)
a = a - b
printf ("%+6s", a/100)
if ( a <= match_a ) {
printf (" YES\n")
} else {
printf (" NO\n")
}
}
....
我将+
留在你的printf语句中,以免弄乱那些需要改变的部分,但你可以摆脱那些因为他们什么都不做的事情。