NumberFormat Parse问题

时间:2011-08-16 09:33:45

标签: java floating-accuracy dataformat decimalformat

我对将字符串解析为Double时遇到的这个特殊的“错误”感到困惑。

我已经设置了NumberFormat属性和符号。

传递一个15位和2位小数的字符串(例如str = "333333333333333,33") 并使用Number num = NumberFormat.parse(str)解析它,结果是省略了数字。

num的实际值为3.333333333333333E14

它似乎与Strings一起使用所有的1,2和4但是......

任何人都可以启发我吗?

干杯 恩里科

2 个答案:

答案 0 :(得分:6)

答案简短;由于圆误差

(double) 111111111111111.11 != (double) 111111111111111.1

(double) 333333333333333.33 == (double) 333333333333333.3

如果你想要更高的精度,请使用setParseBigDecimal,parse将返回一个BigDecimal。


为什么会这样?这是因为你处于双倍精度的极限。 17个很好,因为它可以代表。 2是两倍,双倍存储2的力量,所有17个中的两个的所有力量,所以17个四分之一和17个八分之一。

但是,17个三分之一比一个代表该值需要多一个位,并且最后一位被截断。同样,17五,六和九也有舍入误差。

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

答案 1 :(得分:5)

在这种情况下,DecimalFormat.parse方法会返回Double,其精度有限

您不能指望它始终能够返回一个完全代表输入的数字。

您可以使用BigDecimal.setParseBigDecimal允许数字格式从解析方法返回BigDecimal。此Number能够以任意精度表示您的值。 (感谢@Peter Lawrey指出这一点!)