2016-06-02 4 views
8

なぜJava +=が間違った結果になるのですか?この問題を防ぐにはどうしたらいいですか? (たとえば、IDEでwarningと表示されていますか?)なぜjava + =結果が間違っていますか?これを防ぐにはどうしたらいいですか?

私は試しました& IntelliJですが、どちらも警告を表示していません。

サンプルコード:bdoubleあるのでJLSによる

{ 
     long a = 20000000000000000L; 
     double b = 90.0; 
     a += b; 
     System.out.println(a); // 20000000000000088 NG 
    } 

    { 
     long a = 10000000000000000L; 
     double b = 90.0; 
     a += b; 
     System.out.println(a); // 10000000000000090 OK 
    } 

    { 
     long a = 20000000000000000L; 
     double b = 90.0; 
     a += (long) b; 
     System.out.println(a); // 20000000000000090 OK 
    } 
+1

その質問@Sotiriosは説明しません。 – 4castle

+0

@ 4castle 'double'の精度は、その小数部に適用されるだけではありません。 –

+0

@SotiriosDelimanolisそれは質問に含まれていない正確な情報です。 [回答](http://stackoverflow.com/a/2607316/5743988)でも、浮動小数点の整数演算は正確であるため、数値を整数にスケーリングすることをお勧めします。 – 4castle

答えて

10

、このcompound assignment expression

a += b; 

は添加が起こる前binary numeric promotionが発生し、

a = (long) (a + b); 

と等価です。両方のオペランドはdoubleの値に変換され、加算は浮動小数点演算で行われます。

20000000000000090は、正確にはdoubleと表すことはできません。したがって、精度が低下し、代わりに20000000000000088が得られます。その後、20000000000000088を表すのに十分な精度を持つlongにキャストバックされます。

10000000000000090の2つ目のスニペットは、doubleと正確に表すことができます。

あなたの第三スニペットはinteger arithmeticを使用しています

a = (long) (a + (long) b); 

に相当します。 20000000000000090は、longと表すことができます。

私はこのことについてあなたに警告するツールがありません。

関連:

1

Javaは有意を表すために53進数を使用64-bit IEEE floating point numbersを使用します。最初の例では、ここで可変a

{ 
    long a = 20000000000000000L; 
    double b = 90.0; 
    a += b; 
    System.out.println(a); // 20000000000000088 NG 
} 

は、それを表すために、1より大きい指数を使用する必要があり、二重に変換され、それはもはや値20000000000000000Lの正確な表現でないであろう。この例では

は、それだけ仮数とこの例で

{ 
    long a = 10000000000000000L; 
    double b = 90.0; 
    a += b; 
    System.out.println(a); // 10000000000000090 OK 
} 

の指数を使用してaを表現することが可能である、b明示的にaを変換する必要性を回避し、longに変換され倍精度浮動小数点演算を実行します。

{ 
    long a = 20000000000000000L; 
    double b = 90.0; 
    a += (long) b; 
    System.out.println(a); // 20000000000000090 OK 
} 
0

のように(私のような)全てのプログラマが不足しているコーディングなど+=を防止するためbinary numeric promotion

を理解することができない、私は簡単な方法を見つけました:ちょうどルールをコーディングすると、すべての+=を禁じます。

私は自分のプロジェクトで+=をgrepし、a += ba = a + bに変更しました。

タイプは怒鳴るよう、+操作しながら、一致していながら、IDEがエラーを示していますなし小数部分を持つ数は、この動作を持っているでしょう、なぜ

IDE show compile errors

関連する問題