-1

Javaのdouble変数で非常に奇妙な動作が見られました。これは、doubleに小さな小数部を追加しようとしているだけで、完全に奇妙な結果が表示されるためです。

double test = 0;
test += 0.71;
test += 0.2;

これで、結果は次のようになると思います。

test = 0.91

右?間違い!

実際には、これは私のテストダブルで得られる数です。

test = 0.9099999999999999

さて、これは非常に近いですが、それは非常に奇妙な分数の損失であり、長期的には私のプログラムに深刻なバグを引き起こします。

フロートを使用すると、さらに奇妙な結果が得られます。

どんな助けでも大歓迎です。

ありがとう

4

4 に答える 4

4

それについて奇妙なことは何もありません。0.91、0.71、0.2 は IEEE754 浮動小数点値として表現できません。2 進数で表現すると小数部分が繰り返されるためです。この状況は、10 進法で 1/3 を有限の桁数で表そうとすることに完全に似ています。あなたはそれをすることはできません。

表示されているのは、浮動小数点計算を行う際に発生する通常の丸め誤差です。その周りをコーディングする必要があります。したがって、たとえば、等しいかどうかを確実に比較することはできません。2 つの数値が互いにわずかなデルタ内にあることを確認する必要があります。もう少し詳細でわかりやすい説明については、The Floating Point Guideを参照してください。

于 2012-04-25T10:16:20.393 に答える
1

これが浮動小数点値のバイナリエンコーディングの魔法です(IEEE754を探してください:http://en.wikipedia.org/wiki/IEEE_754-2008)。あなたがこの種のものを決して持たないことを確実にしたいなら、あなたは多分BigDecimalを探しています:

http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigDecimal.html

基本的なルール :

  • 浮動小数点数を処理するときに等式テストを使用しないでください(ギャップをテストする必要があります)
  • 表示している丸め数値(通常はDecimalFormatを使用)
  • 金融アプリケーションに浮動小数点数を使用しないでください
  • IEEE754を理解している限り、フロートは通常、科学的または産業的な運用に使用する方法です。
于 2012-04-25T10:11:34.627 に答える
1

doubleほとんどの小数値しか近似できません。これは、期待どおりの結果を得るには、丸めを使用する必要があることを意味します。または、この問題を処理する BigDecimal を使用できます。

double test = 0;
test += 0.71;
test += 0.2;
System.out.printf("%.2f%n", test);

版画

0.91

自分の利益のために

System.out.println("0.71 is actually " + new BigDecimal(0.71));
System.out.println("0.2 is actually " + new BigDecimal(0.2));
System.out.println("0.71+0.2 is actually " + new BigDecimal(0.71 + 0.2));
System.out.println("0.91 is actually " + new BigDecimal(0.91));
System.out.println("0.71+0.2 == 0.91 is " + (0.71 + 0.2 == 0.91));

版画

0.71 is actually 0.70999999999999996447286321199499070644378662109375
0.2 is actually 0.200000000000000011102230246251565404236316680908203125
0.71+0.2 is actually 0.9099999999999999200639422269887290894985198974609375
0.91 is actually 0.91000000000000003108624468950438313186168670654296875
0.71+0.2 == 0.91 is false
于 2012-04-25T10:15:35.607 に答える
0

Java では、浮動小数点と呼ばれるものを使用して 10 進数を表します。それらは指数表記を使用します。これが私が意味することです:

乗数 (M) と、1023 ~ -1022 の指数 (E) があります。

数値 (N) は次のように表されますM * 2^E

4.25 は次のように表されます。

17 * 2^-2。

0.91 は基数 2 で正確に表すことはできませんが、Java はかなり近くなります。

0.909999999999..

したがって、これらの数値を正確に合計することは不可能です。

于 2016-01-31T18:13:28.603 に答える