在Java中如何表示负整数的二进制形式

19

请帮我理解负整数的二进制表示。

例如我们有数字5。5的二进制表示为00000000.00000000.00000000.00000101

根据我的理解,-5的二进制表示应该是10000000.00000000.00000000.00000101

但实际输出的是11111111.11111111.11111111.11111011

我有2个问题:

1)为什么有这么多1位。

2)我真的无法理解最后三位011。它看起来像是3。即使+1或- 1,它也将是100010

谢谢


2
请阅读关于二进制补码的内容。 - Oliver Charlesworth
6个回答

49

你对负数的理解存在误区。Java使用二进制补码表示负数,基本规则是取绝对值,按位取反再加1,这样就得到了对应的负数。

因此,正如你所说,5是:

0000...00000101

反转后得到:

1111...11111010

然后加上一个会得到:

1111...11111011

你展示的 位模式 是所谓的 sign/magnitude,在这种表示法中,只需翻转最左边的位即可对数字取反。这是 C 实现中允许的三种表示方法之一(a),但 Java 只使用二进制补码表示负整数。


(a) 但请注意,现在 C 和 C++ 中正努力删除其他两种编码类型,只允许二进制补码。


7

据我所知,-5的二进制表示应该是 10000000.00000000.00000000.00000101

如果Java使用符号加绝对值整数表示法,那么这样做就没问题了。然而,Java使用二进制补码表示法,因此其余的位根据该表示法的规则进行更改。

二进制补码表示法背后的思想是,当你在这种表示法下将一个数与另一个值相加并丢弃最高位上的额外位时,结果就好像你减去了同样大小的正数。

你可以用十进制数字来说明这一点。在两位数的表示中,99的值就像-1,98就像-2,97就像-3,以此类推。例如,在23 + 99 = [1]22中,如果你去掉顶部数字,那么99的行为就像-1。23 + 98 = [1]21,所以98的行为就像-2。
使用二进制数字的二进制补码表示方式也是如此,只是你需要去掉顶部的额外位。

4

以下是2的补码的一个示例:

如果你有一个-30,想要用2的补码来表示它,你需要先得到30的二进制表示形式:

0000 0000 0000 0000 0000 0000 0001 1110

然后翻转这些数字。

1111 1111 1111 1111 1111 1111 1110 0001

再加上一。

1111 1111 1111 1111 1111 1111 1110 0010

将其转化回十六进制,得到 0xFFFFFFE2。实际上,假设你有下面这段代码:

#include <stdio.h>

int main() {
    int myInt;
    myInt = 0xFFFFFFE2;
    printf("%d\n",myInt);

    return 0;
}

执行此代码应该输出-30,如果您愿意可以尝试一下。


3

http://zh.wikipedia.org/wiki/二補數

负数的存储方法是将最高有效位(例如32位数字的2^31位)视为负数。因此,如果您存储了所有1s,则会相加。

(-2^31) + 2^30 + 2^29 + ... + 2^1 + 2^0

这将使-1变得更加普遍。

在这种表示法下,小的负数大部分将是1。


1
使用二进制补码表示时,最高位为1表示负数。但是剩余的位不是它的值的二进制表示形式。
另一方面,如果最高位为0,则剩余的位表示二进制值。但不能说这个数字是正数。零既不是正数也不是负数。
这张图片 number circle 帮助我理解了当我开始学习数字的多种表示方式时的原理。
           0
    -1    000    1
       111   001  
-2  110         010  2
       101   011
    -3    100    3
          -4

或者如上链接:


0

https://dev59.com/tV8d5IYBdhLWcg3w41nz#26315812 这个链接解释了如何得到二进制的补码。但是我写这个答案是为了直观地理解二进制的补码,以及它如何表示一个数的负数。

  1. 假设我们使用32位整数,并且第一位(即最高位)的方向是-1,而不是通常的1。这是什么意思呢?如果给你一个二进制数101,它表示的是 (+1)*(2^2) + (0)*(2^1) + (+1)*(2^0)。然而,如果最高位被设置为1,它表示的是 (-1)*(2^31)
  2. 假设x是我们原始的正数。我们假设翻转除了最高位之外的所有位,得到一个数y。现在 x + y = 2^31 - 1
  3. 通过重新排列,我们得到 -x = -(2^31) + y + 1
仔细看一下最后一个方程式的右手边。我们通过最高有效位得到-(2^31)。y是通过翻转所有位得到的。然后我们再加1。这正是我们进行二进制补码的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接