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。


为什么会这样?这是因为您处于双精度的极限。17个很好,因为它可以代表。2 只是这个的两倍,因为 double 存储了 2 的幂,所以 17 个 4 和 17 个 8 都可以。

但是,17 个三分球比 double 多一个位来表示该值,并且最后一位被截断。同样,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
于 2011-08-16T09:51:27.267 回答
5

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

你不能指望它总是能够返回一个精确代表输入的数字。

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

于 2011-08-16T09:38:44.680 回答