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

时间:2015-08-17 03:26:23

标签: java integer-overflow

在回答this question后,我很困惑为什么此代码中的溢出整数导致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

1 个答案:

答案 0 :(得分:11)

仅当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