3

String を Double に解析するときに発生するこの独特の「エラー」について、私はかなり混乱しています。

NumberFormatプロパティとシンボルは既に設定済みです。

15 桁と小数点以下 2 桁の文字列 (例: str = "333333333333333,33") を渡し、結果で解析するとNumber num = NumberFormat.parse(str)、桁が省略されます。

num の実際の値は です3.333333333333333E14

ただし、すべて1、2、および4の文字列で動作しているようです...

誰でも私を啓発できますか?

乾杯エンリコ

4

2 に答える 2

6

短い答え; ラウンドエラーのため

(double) 111111111111111.11 != (double) 111111111111111.1

しかし

(double) 333333333333333.33 == (double) 333333333333333.3

さらに精度が必要な場合は、setParseBigDecimal を使用すると、parse は BigDecimal を返します。


なぜこれが起こるのですか?これは、double の精度の限界に達しているためです。17個は表現できるので問題ありません。2 はこれの 2 倍であり、double は 2 の累乗を格納するため、17 個すべての 2 の累乗が格納されるため、17 個の 4 と 17 個の 8 は問題ありません。

ただし、17 個の 3 は double が値を表すために必要なビットよりも 1 ビット多く必要であり、この最後のビットは切り捨てられます。同様に、17 個の 5、6、および 9 にも丸め誤差があります。

double[] ds = {
        111111111111111.11,
        222222222222222.22,
        333333333333333.33,
        444444444444444.44,
        555555555555555.55,
        666666666666666.66,
        777777777777777.77,
        888888888888888.88,
        999999999999999.99};
for (double d : ds) {
    System.out.println(d + " - " + new BigDecimal(d));
}

以下を出力します。はdouble印刷前にわずかに丸められ、BigDecimal は double が表す正確な値を示します。

1.1111111111111111E14 - 111111111111111.109375
2.2222222222222222E14 - 222222222222222.21875
3.333333333333333E14 - 333333333333333.3125
4.4444444444444444E14 - 444444444444444.4375
5.5555555555555556E14 - 555555555555555.5625
6.666666666666666E14 - 666666666666666.625
7.777777777777778E14 - 777777777777777.75
8.888888888888889E14 - 888888888888888.875
1.0E15 - 1000000000000000
于 2011-08-16T09:51:27.267 に答える
5

この場合、メソッドは精度が制限されDecimalFormat.parseた を返します。Double

入力を正確に表す数値を常に返すことができるとは期待できません。

を使用して、数値形式が parse メソッドからBigDecimal.setParseBigDecimala を返すようにすることができます。BigDecimalこれNumberは、任意の精度で値を表すことができます。(指摘してくれた@Peter Lawreyに感謝します!)

于 2011-08-16T09:38:44.680 に答える