37

したがって、JavaでDoublesを使用して加算または減算すると、奇妙な結果が得られます。ここにあるいくつかの:

を追加する0.0 + 5.1と、が得られます5.1。そのとおりです。

を追加すると、次の5.1 + 0.1ようになります5.199999999999(繰り返し9の数がオフになっている可能性があります)。それは間違っている。

を引く4.8 - 0.4と、それが得られます4.39999999999995(繰り返しますが、9sがオフになっている可能性があります)。それは間違っている。

最初は、これは10進値でdoubleを追加する場合の問題だけだと思いましたが、間違っていました。以下は正常に機能しました。

5.1 + 0.2 = 5.3
5.1 - 0.3 = 4.8

これで、最初に追加された数値は変数として保存されたdoubleですが、2番目の変数はからテキストを取得しますJTextField。例えば:

//doubleNum = 5.1 RIGHT HERE
//The textfield has only a "0.1" in it.
doubleNum += Double.parseDouble(textField.getText());
//doubleNum = 5.199999999999999
4

2 に答える 2

36

Javaでは、double値はIEEE浮動小数点数です。2の累乗(または2の累乗の合計、たとえば1/8 + 1/4 = 3/8)でない限り、高精度であっても正確に表すことはできません。一部の浮動小数点演算は、これらの浮動小数点数に存在する丸め誤差を悪化させます。上で説明した場合、浮動小数点エラーは出力に表示されるほど重大になっています。

数値のソースが何であるかは関係ありません。それがから文字列を解析するのか、リテラルJTextFieldを指定するのかは関係ありませんdouble。問題は浮動小数点表現に継承されます。

回避策:

  • 小数点が非常に多いことがわかっている場合は、整数演算を使用してから、小数点に変換します。

    (double) (51 + 1) / 10
    (double) (48 - 4) / 10
    
  • BigDecimalを使用する

  • を使用する必要がある場合は、 KahanSummationAlgorithmdoubleを使用して浮動小数点エラーを削減できます。

于 2013-03-25T21:57:51.040 に答える
2

Javaでは、doubleはIEEE 754浮動小数点演算(このウィキペディアの記事を参照)を使用しますが、これは本質的に不正確です。完全な小数精度にはBigDecimalを使用してください。印刷を丸めるには、単に「かなり良い」精度を受け入れて、を使用しますprintf("%.3f", x)

于 2013-03-25T21:59:43.803 に答える