为何int连乘后转long结果错误?ci1值异常原因解析
解答:int类型相乘溢出与类型提升问题
咱们直接来解决你的两个疑问,再拆解背后的细节:
1. 为什么变量ci1会存储错误的值?
核心原因是int类型的溢出:im1是int类型,当你执行im1 * im1 * im1的时候,所有乘法运算都是在int的取值范围内进行的。咱们算个数:63360的三次方是254358061056000,这可比int类型的最大值(2^31-1,也就是2147483647)大太多了。
Java里整数溢出不会抛出任何异常,只会偷偷截断超出32位的二进制数据,得到一个错误的数值,之后再把这个错值赋值给long类型的ci1——这时候再转long也没用,数据已经丢了,所以ci1就存了错误的结果。
2. 将三个int类型数值相乘后转换为long类型时,究竟发生了什么?
这里的关键是Java的类型提升规则:
- 像
ci1的情况:先让三个int相乘,结果还是int,已经溢出变错了,再转long也救不回来。 - 而
im2是long类型,当你算im2 * im2 * im2时,Java会自动把所有参与运算的数都提升成long类型(只要运算里有一个long,其他整数类型都会跟着转long)。long的最大值是2^63-1,完全装得下63360的三次方,所以整个运算都在安全的范围内,结果自然是对的。
额外补充:怎么避免这种溢出?
如果手头是int变量,但想计算乘积不溢出,只要在运算前把其中一个变量转成long就行,比如:
ci1 = (long)im1 * im1 * im1;
这样第一个乘法就会触发类型提升,后面的运算都在long范围内进行,结果就正确了。
内容的提问来源于stack exchange,提问作者MCorkers




