我一直在探索Java如何处理整数上溢和下溢,我遇到了以下两种情况:
如果将超出范围的值直接分配给int,则可能不会出现环绕,这取决于转换:
long tooBigLong=2147483648L;
int integerL=(int)tooBigLong;
double tooBigDouble=Math.pow(2, 31);
int integerD=(int)tooBigDouble;
结果:
Converted from Long to int: -2147483648
Converted from Double to int: 2147483647
似乎只有当我从Long转换为int时才会出现整数环绕。
但我确实想弄清楚它怎么不适用于double-to-int转换?谢谢你的帮助!
JLS指定了5.1.3的规则。缩小基元转换:
铸造long
至int
:时
将带符号整数缩窄转换为整数类型T只会丢弃除n个最低阶比特外的所有比特,其中n是用于表示类型T的比特数。除了可能丢失有关数值大小的信息外,这可能会导致结果值的符号与输入值的符号不同。
因此,在您的示例中,删除原始长的前32位并保留后32位会导致负int
。
将double
铸造到int
时:
将浮点数缩小为整型T需要两个步骤:
在第一步中,如果T是长的,则将浮点数转换为long,或者如果T是字节、短、char或int,则将其转换为int,如下所示:
如果浮点数为NaN(§4.2.3(,则第一步转换的结果为int或long 0。
否则,如果浮点数不是无穷大,则浮点值四舍五入为整数值V,使用IEEE 754向零舍入模式(§4.2.3(向零舍入。然后有两种情况:
a。如果T是长的,并且这个整数值可以表示为长,那么第一步的结果是长值V。
b。否则,如果这个整数值可以表示为int,那么第一步的结果就是int值V。
否则,以下两种情况之一必须为真:
a。该值必须太小(大幅度或负无穷大的负值(,并且第一步的结果是int或long类型的最小可表示值。
b值必须太大(大幅度或正无穷大的正值(,并且第一步的结果是int或long类型的最大可表示值
突出显示的部分确定(int)tooBigDouble
应产生Integer.MAX_VALUE
。对于较高的double
值,会得到相同的结果。例如,对于double tooBigDouble=Math.pow(2, 39);