`(long)(float)Long.MAX_VALUE` 有准确的值,这怎么可能?
`(long)(float)Long.MAX_VALUE` has the exact value, how is that possible?
Long
的字节数比 Float
多,所以我预计最高 long 可能不会准确地存储在浮点数中。确实是这样:
System.out.println(String.format("%d", Long.MAX_VALUE));
// 9223372036854775807
System.out.println(String.format("%.0f", (float)Long.MAX_VALUE));
// 9223372036854776000
但是 如果我将这个 float 转换回 long,我怎么可能取回原始值?
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 真的忽略了 'cast' 即使它被存储了吗?我觉得不应该那样做;它改变了结果。
编辑 2(错误,撤消)
问题是因为(float)Long.MAX_VALUE
的结果超出了long
的范围。所以当它转换回来时,它被限制在最大可表示值。
来自 JLS(强调我的):
A narrowing conversion of a floating-point number to an integral type T takes two steps:
[...]
Otherwise, one of the following two cases must be true:
[...]
The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest representable value of type int or 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 推荐的示例。)
Long
的字节数比 Float
多,所以我预计最高 long 可能不会准确地存储在浮点数中。确实是这样:
System.out.println(String.format("%d", Long.MAX_VALUE));
// 9223372036854775807
System.out.println(String.format("%.0f", (float)Long.MAX_VALUE));
// 9223372036854776000
但是 如果我将这个 float 转换回 long,我怎么可能取回原始值?
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 真的忽略了 'cast' 即使它被存储了吗?我觉得不应该那样做;它改变了结果。
编辑 2(错误,撤消)
问题是因为(float)Long.MAX_VALUE
的结果超出了long
的范围。所以当它转换回来时,它被限制在最大可表示值。
来自 JLS(强调我的):
A narrowing conversion of a floating-point number to an integral type T takes two steps:
[...]
Otherwise, one of the following two cases must be true:
[...]
The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest representable value of type int or 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 推荐的示例。)