为什么这个乘法整数溢出会导致零?

在回答了这个问题后 ,我很困惑为什么这段代码中的溢出整数导致0而不是负数。 这很奇怪,为什么这么准确? 为什么0?

 public class IntegerOverflow { public static void main(String[] args) { int x = 10; int i = 0; for (i = 0; i <= 5; i++) { x = x * x; System.out.println(x); } } } 

输出:

 100 10000 100000000 1874919424 0 0 

只有当x的起始值是偶数时才会发生这种情况。

根据JLS§15.17.1 :

如果整数乘法溢出,则结果是数学乘积的低阶位 ,如某些足够大的二进制补码格式所示。 结果,如果发生溢出,则结果的符号可能与两个操作数值的数学乘积的符号不同。

如果我们以二进制格式而不是十进制格式打印数字,这将更加明显:

 public class IntegerOverflow { public static void main(String[] args) { int x = 10; int i = 0; for (i = 0; i <= 5; i++) { x *= x; System.out.println(Integer.toBinaryString(x)); } } } 

输出:

 1100100 10011100010000 101111101011110000100000000 1101111110000010000000000000000 0 0 

如您所见,每次平方时,我们将零位数加倍。 由于只保存了低位,因此每次将零加倍最终将导致零。 请注意,如果x的起始值为奇数, 则不会看到这些尾随零 。 相反,它会导致看似无关的数字,如溢出通常会产生。

 public class IntegerOverflow { public static void main(String[] args) { int x = 11; int i = 0; for (i = 0; i <= 5; i++) { x *= x; System.out.format("%-12d\t%s%n", x, Integer.toBinaryString(x)); } } } 

输出:

 121 1111001 14641 11100100110001 214358881 1100110001101101101101100001 772479681 101110000010110001101011000001 -1419655807 10101011011000011100010110000001 -1709061375 10011010001000011100101100000001