2017-10-01 2 views
1

特定の処理と計算のためにawkを使用するbashの関数を持っていて、数値を含む2つの変数の減算結果常に機能するとは限りません。場合によってはawk:2つの変数の減算が不正確な結果を残す非常に小さな残差(e-15)を与える

私はこの(compare.sh)を実証するための一例のコードを作った(サイズe-15で)二つの変数の減算後に残ったいくつかの非常に小さな数を残すことは、AWKのように思える

#!/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 

これは、すべての罰金ですが、私が代わりに4.5の例3.75に(a)の値を開始するために変更した場合、その後の奇妙な何かが起こっている、

$ ./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 /オラ

+4

[すべてのプログラマが浮動小数点演算について知っておくべきこと](http://floating-point-gui.de/) – choroba

答えて

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文で+秒を残したが、あなたは得ることができます彼らは何もしていないので、それらを取り除く。

関連する問題