整数溢出 Java [重复]

问题描述 投票:0回答:1

我在 Java 中有一个关于整数溢出的问题。

当我搜索该二进制文件的最大整数和冲浪整数时,我得到了这个“0111 1111 1111 1111 1111 1111 1111 1111”,当我使用值 3 时,我得到的二进制文件为“0000 0000 0000 0000 0000 0000 0000 0011” .这怎么可能,因为 2^0+2^1=3?很好,但是对于最大值,2^31 是 2147483648,它仅 2^31 就达到了 int 的最大值,我们仍然不添加剩余的 2^30 +2^29 等等?那么,除了最高位之外,最大整数的所有位是如何变成“1”的呢?

我想知道完整的工作,这些东西是如何工作的。

java integer-overflow
1个回答
0
投票

负数也需要一个槽。计算机只有 1 和 0;没有“减号”。所以我们用零和一“编码”负数。第一位是符号位;如果它是 1,则该数字实际上是负数。因此,为什么最大(非负!)数字是 0111 1111 1111 1111 1111 1111 1111 1111。如您所料,它是十进制的 2^0+2^1+2^2+.....2^ 30.这与 2^31-1 相同,即 2147483647。确实是:

System.out.println(Integer.MAX_VALUE); // prints 2147483647.
System.out.println(0b0111_1111_1111_1111_1111_1111_1111_1111); // same
int v = 0;
for (int i = 0; i < 31; i++) {
  int z = (int) Math.pow(2, i);
  v += z;
}
System.out.println(v); // same

'0'也得去某个地方,而且全是零位。这意味着一个有趣的细节:当然,以 1 位开头的数字和以 0 位开头的数字一样多,但是 0 位空间(我们的正数)需要为零分配一个序列,但负空间没有。因此,您可以表示的最大 negative 数实际上是一个更高的数:它是 -2^31:

System.out.println(Integer.MIN_VALUE);

打印 -2147483648.

负数用2的补码表示。基本上,“反向”。

1000 0000 0000 0000 0000 0000 0000 0000
实际上是-2147483648,而
1111 1111 1111 1111 1111 1111 1111 1111
是-1。你可以阅读例如维基百科关于二进制补码的所有细节,但一个巨大的优势是
+
-
操作(以及增量/减一操作)的工作方式相同,无论您是否将这些位视为无符号(负数)数字是不可能的,可以表示 0 到 2^32-1),或者有符号(负数是可能的,可以表示 -2^31 到 +2^31-1)。现在“它是有符号的还是无符号的”在数学上是无关紧要的,这样可以节省指令。

快速启蒙:取 -1 的二进制补码(以位为单位:32x

1
),然后加 1。这通常会导致 1 后跟 32 个零,并且由于计算机只是去掉多余的部分,所以只有 32 个零位。代表零。 -1 增加 1 是.. 确实为零。整洁!

2 的补码归结为“翻转所有位并加一”,例如:

  • 5 = 0000.....0101
  • -5 因此变成:1111....1011.
  • 反转该操作再次产生 000...0101。
© www.soinside.com 2019 - 2024. All rights reserved.