为什么(长)9223372036854665200d给我9223372036854665216?

时间:2011-10-18 17:14:31

标签: java casting double long-integer

我知道有精确错误的怪异东西,但我无法理解,

(long)9223372036854665200d为什么要给我9223372036854665216

5 个答案:

答案 0 :(得分:34)

9223372036854665200ddouble类型的常量。但是,9223372036854665200不适合double而不会损失精度。 double只有52位尾数,而有问题的数字需要63位才能准确表示。

最接近的double9223372036854665200d是尾数等于1.1111111111111111111111111111111111111111111110010100的二进制数,其指数为63(十进制)。这个数字不是9223372036854665216(称之为U)。

如果我们将尾数减少一个等级到1.1...0011,我们得到9223372036854664192(称之为L)。

原始数字介于LU之间,距U更接近L

最后,如果你认为这个尾数的截断应该导致一个以一串零结尾的数字,那么你是对的。只有它以二进制形式发生,而不是十进制:基数为16的U0x7ffffffffffe5000L0x7ffffffffffe4c00

答案 1 :(得分:16)

因为双打没那么精确。你为什么这么奇怪?将d更改为l。

答案 2 :(得分:6)

Doubles具有52-53位精度,而long具有64位精度(仅适用于整数)。 double中的精度损失用于表示指数,这允许double表示比long更大/更小的数字。

您的号码长度为19位,而双倍号码只能存储大约16位数的(十进制)整数数据。因此,最终的数字最终会被舍入。

参考:Double - Wikipedia

答案 3 :(得分:5)

因为双打有限precision。你的常数有一个比双重记录更多的有效数字,所以它会丢失它们。

答案 4 :(得分:3)

您假设有限精度意味着它以十进制表示,因此限制为15或16位数。实际上它以二进制表示,并且限制为53位精度。 double采用最接近的可表示值。

double d = 9223372036854665200d;
System.out.println(d +" is actually\n" + new BigDecimal(d)+" so when cast to (long) is\n"+(long) d);

打印

9.2233720368546652E18 is actually 
9223372036854665216 so when cast to (long) is 
9223372036854665216