java - 为什么2147483647 + 1实际上是-2147483648?

标签 java overflow

在我的java教科书中,它写着“2147483647 + 1实际上是-2147483648”

我知道这是因为溢出,但为什么他们选择让它等于最小整数值?

最佳答案

没有人“选择”溢出以这种方式工作,这是补码表示中加法的自然结果。 32 位数字可以表示 4,294,967,296 个不同的值。无符号数(Java 没有)的范围为 [0..4,294,967,295]。

二进制补码分割整个范围,使其一半代表 >= 0 的数字,另一半代表 < 0 的数字,并且它以易于在硬件中实现的方式实现这一点。

让我们以二进制形式向下计数

    Decimal          Binary
-----------      -----------------------------------     
          2      00000000 00000000 00000000 00000010
          1      00000000 00000000 00000000 00000001
          0      00000000 00000000 00000000 00000000
         -1      11111111 11111111 11111111 11111111
         -2      11111111 11111111 11111111 11111110

如果您将二进制数视为汽车上的里程表,这可能会有所帮助。不同之处在于该计数器可以朝任一方向移动。因此,当向下计数时,当它为零时,它会返回到最大的无符号正数。二进制补码的作用是将位模式(全 1)称为 -1,因此不需要特殊的硬件来容纳它,并且计数行为在零处连续。这有两个后果

  1. 最左边的位告诉我们该数字是正数 (0) 还是负数 (1)
  2. 由于零处不存在不连续性,因此您可以将负数和正数相加并获得正确的结果,而无需任何特殊考虑。进行算术运算,将二进制 +1 和 -1 相加,得到零。

现在让我们看看事情的另一端。继续减去,直到得到:

    Decimal          Binary
-----------      -----------------------------------     
-2147483647      10000000 00000000 00000000 00000001
-2147483648      10000000 00000000 00000000 00000000

    now, if you subtract 1 more...
          ?      01111111 11111111 11111111 11111111

但生成的位模式只是可以表示的最大数,即 2147483647。将 1 添加回该值,然后返回到最小的负数。

-2147483648      10000000 00000000 00000000 00000000

补码有两种替代方案。补码和“符号幅度”,两者都需要更复杂的硬件来进行算术,因为它们在零处表现出不连续性。两者都有+0和-0,表示方式不同,运算时需要调整。

如果你做与小数的 2 补码相同的事情,它将被称为“十补码”,并且会像这样工作(为简单起见,我将使用 3 位计数器)

Actual     10's complement
 Value     representation
------     ---------------
 499          499
   2          002
   1          001
   0          000
  -1          999
  -2          998
-499          501
-500          500

与 2 的补码相同,我们采用 0-999(1000 个值)的无符号范围并将其拆分,以便一半 (0-499) 代表零和正值,另一半 ( 500-999) 代表负数。

关于java - 为什么2147483647 + 1实际上是-2147483648?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48160580/

相关文章:

java - 更大元素的数组

java - 如何使用 Java SDK 将目录与 AWS S3 同步?

css - 溢出问题

overflow - 在外部 div 上使用 CSS max-height 强制在内部 div 上滚动

Clojure 堆栈溢出使用 recur、lazy seq?

html - 使用 Overflow-y :scroll 将 child 拖出容器

java - 比较两个arrayList得到共同的值,并且它应该不影响原始值

java - Web 应用程序的单一数据库连接

java - WEKA - 对来自 Java 的新数据进行分类 - IDF 转换

HTML 表格溢出到相邻的 Div