为什么这个乘法整数溢出会导致零?
Why does this multiplication integer overflow result in zero?
在回答了之后,我很困惑为什么这段代码中溢出的整数会导致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:
If an integer multiplication overflows, then the result is the low-order bits of the mathematical product as represented in some sufficiently large two's-complement format. As a result, if overflow occurs, then the sign of the result may not be the same as the sign of the mathematical product of the two operand values.
如果我们以二进制格式而不是十进制格式打印数字,这会变得更加明显:
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
在回答了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:
If an integer multiplication overflows, then the result is the low-order bits of the mathematical product as represented in some sufficiently large two's-complement format. As a result, if overflow occurs, then the sign of the result may not be the same as the sign of the mathematical product of the two operand values.
如果我们以二进制格式而不是十进制格式打印数字,这会变得更加明显:
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