这是一块非常简单的Java代码片段:
public class HelloWorld{ public static void main(String []args){ int product = 1; for (int i = 10; i <= 99; i++) { product *= i; } System.out.println(product); }}
为什么得出的后果是0呢?
问题景象
蛋疼的同学可能会发现这个程序执行的法则:
1 * 10 = 10
10 * 11 = 110
110 * 12 = 1320
1320 * 13 = 17160
17160 * 14 = 240240
240240 * 15 = 3603600
3603600 * 16 = 57657600
57657600 * 17 = 980179200
……
-1342177280 * 40 = -2147483648
-2147483648 * 41 = -2147483648
-2147483648 * 42 = 0
0 * 43 = 0
0 * 44 = 0
……
0 * 97 = 0
0 * 98 = 0
程序从42开始就曾经输入0,所以42当前的数字相乘的后果就不言而喻了。从后果中发现,乘积的符号已一种难以了解的形式变换着,表明乘积曾经溢出了,同时也阐明Java并不会理睬整数的高低溢出。
问题解答
请记住Java的int类型是32位的有符号二进制补码示意的数字类型(译者注:64为jdk同样如此)。这是每一步乘法在计算机外部所做的操作:
标注(1)是理论十进制后果。
标注(2)十六进制以及十进制的外部示意后果,int类型只会存储低32位的数据。
标注(3)是标注(2)的补码模式。
如果你好奇0从哪里来,请认真看上方2进制示意的后果。仔细的同学会留神到:
任何一个数与偶数相乘得偶数。
偶数与偶数相乘,会将2进制位整体左移,0从左边填补空位。
偶数与奇数相乘,不会扭转最右方0的数量。
当乘法执行的足够屡次时,右方的0位会越来越多。最终,间断乘到42时,乘积的2进制示意的低32位全是0,所以int将会是0。
问题扩大
既然晓得了问题的起因,咱们换一种变量来做同样的操作,以byte为例。
Java的byte变量是8位的有符号数,同样也是补码示意。从上方后果表格看出,间断从10乘到16时,2进制后果的低8位全都是0,所以此时的byte变量是0。而间断乘到15时,低8位是10010000,还记得怎么由补码求原码吗?很简略, 符号位不变,其余位取反加1,得出11110000,既-112,感兴趣的敌人请在本人机器上验证后果。有趣味的同学能够退出技术探讨群:626267345