对于超出整数范围的数字,整数类型转换如何在Java中表现?

时间:2017-03-21 10:06:48

标签: java casting

这是我的计划。

public class Foo
{
    public static void main(String[] args)
    {
        System.out.println((int) 2147483648l);
        System.out.println((int) 2147483648f);
    }
}

这是输出。

-2147483648
2147483647

为什么不将2147483648l2147483648f类型转换为相同的整数?你能解释一下这里发生了什么,或者我需要了解Java中的哪些概念来预测像这样的类型转换的输出?

2 个答案:

答案 0 :(得分:74)

这些是Narrowing Primitive Conversion操作的示例。

在您的第一个示例中,longint

  

有符号整数到整数类型T的缩小转换只会丢弃除n个最低位之外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关幅度的信息之外数值,这可能导致结果值的符号与输入值的符号不同。

因此,您的(int) 2147483648l占据long的64位:

00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000

...并完全删除前32位:

10000000 00000000 00000000 00000000

...并将剩余的32位作为int。由于其中最左边的一个是符号位(longint存储为两个补码),并且因为它恰好设置在您的2147483648l值中,所以最终会得到一个符号位负数。由于没有设置其他位,以二进制补码表示您具有最低负数int可以表示:-2147483648。

floatint示例遵循更复杂的规则。您的价值的相关部分是:

  

...如果浮点数不是无穷大,浮点值将四舍五入为整数值V,使用IEEE 754舍入为零的模式(§4.2.3)向零舍入。 / p>      

... [if]值[is]太大(大幅度或正无穷大的正值),[then]第一步的结果是int或long类型的最大可表示值。

(但请参阅上面链接的规范部分以获取详细信息。)

因为2147483648f轮到2147483648,而2147483648太大而无法放入intint的最大值2147483647而是用来代替。

所以在longint,它有点摆弄;在floatint中,它更具数学性。

在评论中你问过:

  

您知道为什么(short) 32768(short) 32768f都评估为-32768吗?我正在考虑将后者评估为32767

很好的问题,这就是我的“看到上面链接的规范的一部分,上面有详细信息”进来。:-) (short) 32768f实际上是{{1 }}:

在上面链接的规范部分中,“将浮点数转换为整数类型T需要两个步骤:”,它说

  
      
  1. 在第一步中,如果T为(short)(int)32768f,则浮点数转换为long,如果T为long,则转换为intbyteshortchar ...
  2.   

然后在第2步的第二个子弹中:

  
      
  1. *如果T为intbytechar,则转换结果是结果转换为类型T(第5.1.3节)的结果第一步。
  2.   

因此,在第一步中,short变为32768f32768值),当然int执行我们在(short)32768中看到的位斩} =>上面long,给我们intshort

答案 1 :(得分:20)

尼斯!能够以您的方式呈现设计决策的效果,真是太棒了。

unsafe-inline2147483648l类型,规则用于转换long对于long来说太大了将环绕规则应用于目标类型。 (在引擎盖下,源类型的重要位被简单地丢弃。)

int2147483648f类型,规则用于转换对目标类型来说过大的float是最大的可能是目的地类型。参考Are Java integer-type primitive casts "capped" at the MAX_INT of the casting type?

标准的好处在于有很多选择。