int溢出场景下使用1与1.0运算后转换为double的结果差异疑问
int溢出场景下使用1与1.0运算后转换为double的结果差异疑问
先来看你的代码和输出:
public class foo { public static void main(String [] args){ int a = (int) Math.pow(2, 30); double d = (a + a - 1.0); double f = (a + a - 1); System.out.println(d); System.out.println(f); } }
输出结果:
-2.147483649E9 2.147483647E9
你的疑惑我完全理解,一开始碰到这种情况确实容易懵,咱们一步步拆解问题的核心:
首先明确几个关键前提:
a的值是2^30也就是1073741824,这个值在int的范围内(int最大值是2^31-1=2147483647),没问题。a+a等于2147483648,这已经超过了int的最大值,触发整数溢出,按照Java的补码规则,这个值会变成int的最小值:-2147483648。
现在分别看两个表达式的运算逻辑:
第一个表达式:a + a - 1.0
这里运算时遇到了1.0这个double类型的值,Java会先把前面溢出后的int结果(-2147483648)转换成double类型(也就是-2147483648.0),然后再做减法:-2147483648.0 - 1.0 = -2147483649.0,也就是你看到的-2.147483649E9。
第二个表达式:a + a - 1
这里的所有运算都是int类型的!第一步a+a溢出得到-2147483648,接下来用这个值减1(int类型),这时候又触发了一次溢出——因为-2147483648是int能表示的最小值,再减1的话,补码运算会让它循环到int的最大值:2147483647。最后把这个int值转换成double,就得到了2147483647.0,也就是输出的2.147483647E9。
简单总结一下:
- 第一个表达式因为有double参与,提前把溢出后的int转成了double,后续减法是double运算,不会再溢出;
- 第二个表达式全程都是int运算,溢出后再减1又一次溢出,结果变成了int的最大值,最后才转成double。
备注:内容来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

