`(long)(float)Long.MAX_VALUE`具有确切的值,这怎么可能?

时间:2017-04-07 13:25:31

标签: java casting floating-point precision

Long的字节数多于Float,因此我预计最高的长度可能不会完全存储在浮点数中。确实如此:

System.out.println(String.format("%d", Long.MAX_VALUE));
// 9223372036854775807
System.out.println(String.format("%.0f", (float)Long.MAX_VALUE));
// 9223372036854776000

但是如果我把这个浮点数转换回来,我怎么可能得到原来的值呢?

System.out.println(String.format("%d", (long)(float)Long.MAX_VALUE));
// 9223372036854775807

Java是如何以某种方式恢复丢失的精度的?

编辑1 :一些额外信息:

float j = Long.MAX_VALUE;
System.out.println((long)j);
// 9223372036854775807

因此,即使存储了值,效果也是一样的。 Java是否真的忽略了'演员',即使它存储了?我觉得不应该这样做;它改变了结果。

编辑2(错误,撤消)

1 个答案:

答案 0 :(得分:4)

问题是因为(float)Long.MAX_VALUE的结果超出了long的范围。因此,当它被转换回来时,它会被限制在最大可表示值。

来自JLS(强调我的):

  

将浮点数转换为整数类型T需要两个步骤:

     

[...]

     

否则,以下两种情况之一必须为真:

     

[...]

     

值必须太大(大幅度或正无穷大的正值),第一步的结果是int或long类型的最大可表示值

证明:

long x = Long.MAX_VALUE - 10;
System.out.println(x);                // 9223372036854775797
System.out.printf("%.0f", (float)x);  // 9223372036854776000
System.out.println((long)(float)x);   // 9223372036854775807 (look familiar?)

(感谢@ T.J.Crowder提供的建议示例。)