这是我的计划。
public class Foo
{
public static void main(String[] args)
{
System.out.println((int) 2147483648l);
System.out.println((int) 2147483648f);
}
}
这是输出。
-2147483648
2147483647
为什么不将2147483648l
和2147483648f
类型转换为相同的整数?你能解释一下这里发生了什么,或者我需要了解Java中的哪些概念来预测像这样的类型转换的输出?
答案 0 :(得分:74)
这些是Narrowing Primitive Conversion操作的示例。
在您的第一个示例中,long
到int
:
有符号整数到整数类型T的缩小转换只会丢弃除n个最低位之外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关幅度的信息之外数值,这可能导致结果值的符号与输入值的符号不同。
因此,您的(int) 2147483648l
占据long
的64位:
00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000
...并完全删除前32位:
10000000 00000000 00000000 00000000
...并将剩余的32位作为int
。由于其中最左边的一个是符号位(long
和int
存储为两个补码),并且因为它恰好设置在您的2147483648l
值中,所以最终会得到一个符号位负数。由于没有设置其他位,以二进制补码表示您具有最低负数int
可以表示:-2147483648。
float
到int
示例遵循更复杂的规则。您的价值的相关部分是:
...如果浮点数不是无穷大,浮点值将四舍五入为整数值V,使用IEEE 754舍入为零的模式(§4.2.3)向零舍入。 / p>
... [if]值[is]太大(大幅度或正无穷大的正值),[then]第一步的结果是int或long类型的最大可表示值。
(但请参阅上面链接的规范部分以获取详细信息。)
因为2147483648f
轮到2147483648
,而2147483648
太大而无法放入int
,int
的最大值2147483647
而是用来代替。
所以在long
到int
,它有点摆弄;在float
到int
中,它更具数学性。
在评论中你问过:
您知道为什么
(short) 32768
和(short) 32768f
都评估为-32768
吗?我正在考虑将后者评估为32767
。
很好的问题,这就是我的“看到上面链接的规范的一部分,上面有详细信息”进来。:-) (short) 32768f
实际上是{{1 }}:
在上面链接的规范部分中,“将浮点数转换为整数类型T需要两个步骤:”,它说
- 在第一步中,如果T为
醇>(short)(int)32768f
,则浮点数转换为long
,如果T为long
,则转换为int
,byte
,short
或char
...
然后在第2步的第二个子弹中:
- *如果T为
醇>int
,byte
或char
,则转换结果是结果转换为类型T(第5.1.3节)的结果第一步。
因此,在第一步中,short
变为32768f
(32768
值),当然int
执行我们在(short)32768
中看到的位斩} =>上面long
,给我们int
值short
。
答案 1 :(得分:20)
尼斯!能够以您的方式呈现设计决策的效果,真是太棒了。
unsafe-inline
是2147483648l
类型,规则用于转换long
对于long
来说太大了将环绕规则应用于目标类型。 (在引擎盖下,源类型的重要位被简单地丢弃。)
int
是2147483648f
类型,规则用于转换对目标类型来说过大的float
是最大的可能是目的地类型。参考Are Java integer-type primitive casts "capped" at the MAX_INT of the casting type?
标准的好处在于有很多选择。