awk:两个变量的减法产生非常小的剩余物(e-15),这会产生不正确的结果

时间:2017-10-01 12:18:20

标签: bash awk

我在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 /奥拉

1 个答案:

答案 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语句中,以免弄乱那些需要改变的部分,但你可以摆脱那些因为他们什么都不做的事情。