为什么Double.parseDouble使9999999999999999变为10000000000000000?

时间:2012-01-18 09:15:32

标签: java double

为什么Double.parseDouble将9999999999999999设为10000000000000000? 例如:

Double d =Double.parseDouble("9999999999999999");
String b= new DecimalFormat("#.##").format(d);
System.out.println(b);

IS打印

10000000000000000

而是必须显示99999999999999999999999999999999.00

非常感谢任何形式的帮助。

3 个答案:

答案 0 :(得分:16)

数字9999999999999999刚好高于双精度浮点的精度限制。换句话说,53位尾数无法保持9999999999999999

结果是它被四舍五入到最接近的双精度值 - 10000000000000000

 9999999999999999 = 0x2386f26fc0ffff  // 54 significant bits needed
10000000000000000 = 0x2386f26fc10000  // 38 significant bits needed

答案 1 :(得分:13)

double只有15/16位数的精确度,当你给它一个它不能代表的数字时(大多数情况下,即使0.1不准确)它也需要最接近的可表示数字。< / p>

如果您想完全代表9999999999999999,则需要使用BigDecimal。

BigDecimal bd = new BigDecimal("9999999999999999");
System.out.println(new DecimalFormat("#.##").format(bd));

打印

9999999999999999

很少有真实世界的问题需要这种准确性,因为无论如何你都无法准确地测量任何东西。即每个quintillion的误差为1份。


您可以使用

找到最大的可表示整数
// search all the powers of 2 until  (x + 1) - x != 1
for (long l = 1; l > 0; l <<= 1) {
    double d0 = l;
    double d1 = l + 1;
    if (d1 - d0 != 1) {
        System.out.println("Cannot represent " + (l + 1) + " was " + d1);
        break;
    }
}

打印

Cannot represent 9007199254740993 was 9.007199254740992E15

最大可表示的整数是9007199254740992,因为它需要少一位(因为它的偶数)

答案 2 :(得分:5)

9999999999999999需要54位尾数才能准确表示,而double只有52位。因此,该数字四舍五入到可以表示的最接近的数字使用52位尾数。这个数字恰好是10000000000000000

10000000000000000需要更少位的原因是它的二进制表示以很多零结尾,并且这些零可以通过增加(二进制)指数来表示。

有关类似问题的详细说明,请参阅Why is (long)9223372036854665200d giving me 9223372036854665216?