我只是好奇,为了在二进制中表示-1,是否有一个原因,使用了2的补码:翻转位并加1?

-1由11111111(2的补码)表示,而不是(对我来说更直观)10000001,10000001是二进制1,第一位为负标志。

免责声明:我的工作不依赖二进制算术!


当前回答

维基百科说明了一切:

二补系统的优点是不需要加减电路检查操作数的符号来决定是加还是减。这一特性使系统实现更简单,能够轻松地处理更高精度的算术。此外,零只有一种表示,避免了与负零相关的微妙之处,这种微妙之处存在于补体系统中。

换句话说,无论数字是否为负,加法都是一样的。

其他回答

有不同类型的表示,它们是:

无符号数表示 有符号数字表示 补体表示 二补体表示法

无符号数字表示,仅用于表示正数

有符号的数字表示,用来表示正数和负数。在有符号数表示中,MSB位表示符号位,其余位表示数字。当MSB为0时表示数字为正,当MSB为1时表示数字为负。

有符号数表示的问题是0有两个值。

补码表示法的问题是0有两个值。

但如果我们使用2的补体表示,那么0就只有一个值,这就是为什么我们用2的补体形式表示负数。

来源:负数为什么以二进制补码形式存储

2的补语允许负数和正数相加,而不需要任何特殊的逻辑。

如果你想用你的方法做1和-1相加 10000001 (1) + 00000001 (1) 你得到 10000010 (2)

相反,通过使用2的补数,我们可以相加

11111111 (1) + 00000001 (1) 你得到 00000000 (0)

减法也是如此。

同样,如果你试着用6减去4(两个正数),你可以用2补4,然后把两者相加6 + (-4)= 6 -4 = 2

这意味着正数和负数的减法和加法都可以由cpu中的同一个电路完成。

这样加法就不需要任何特殊的逻辑来处理负数了。在维基百科上查看这篇文章。

假设有两个数,2和-1。在表示数字的“直观”方式中,它们将分别为0010和1001(我坚持使用4位的大小)。两者互为补足,分别是0010和1111。现在,假设我想把它们相加。

2的补语加法非常简单。你通常加数字,任何进位在最后被丢弃。所以它们相加如下:

  0010
+ 1111
=10001
= 0001 (discard the carry)

0001是1,这是“2+(-1)”的预期结果。

但在你的“直观”方法中,添加更复杂:

  0010
+ 1001
= 1011

等于-3,对吧?简单的加法在这种情况下行不通。你需要注意,其中一个数字是负的,如果是这种情况,就使用不同的算法。

对于这种“直观的”存储方法,减法是一种不同于加法的操作,在加法之前需要对数字进行额外的检查。由于您希望最基本的操作(加法、减法等)尽可能快,因此需要以允许您使用尽可能简单的算法的方式存储数字。

此外,在“直观”存储方法中,有两个0:

0000  "zero"
1000  "negative zero"

它们直观上是相同的数字,但存储时有两个不同的值。每个应用程序都需要采取额外的步骤来确保非零值也不是负零。

以这种方式存储int型还有另一个好处,那就是当你需要扩展存储值的寄存器的宽度时。对于2的补数,在8位寄存器中存储一个4位数就是重复它的最高位:

    0001 (one, in four bits)
00000001 (one, in eight bits)
    1110 (negative two, in four bits)
11111110 (negative two, in eight bits)

这只是观察小单词的符号位,然后重复它,直到它赶上大单词的宽度。

使用你的方法,你需要清除现有的位,这是一个额外的操作,除了填充:

    0001 (one, in four bits)
00000001 (one, in eight bits)
    1010 (negative two, in four bits)
10000010 (negative two, in eight bits)

在这两种情况下,您仍然需要设置额外的4位,但在“直观”情况下,您还需要清除第5位。这是每个应用程序中最基本和最常见操作之一中的一个小小的额外步骤。

尽管这个问题已经很老了,但还是让我说说我的看法。

在我解释这个之前,让我们回到基础上来。2'补码等于1'补码+ 1。 那么1的补是什么,它的加法意义是什么。

任何n位数和它的1的补数的和给出了可以用这n位表示的最大可能的数。 例子:

 0010 (2 in 4 bit system)
+1101 (1's complement of 2)
___________________________
 1111  (the highest number that we can represent by 4 bits)

现在如果我们尝试在结果中再加1会发生什么。这将导致溢出。

结果将是1 000,即0(因为我们处理的是4位数字,(左边的1是溢出)

So ,

Any n-bit number + its 1's complement = max n-bit number
Any n-bit number + its 1'complement + 1 = 0 ( as explained above, overflow will occur as we are adding 1 to max n-bit number)

于是有人决定把1的补体+ 1称为2'补体。所以上面的表述变成: 任何n位数+它的2的补= 0 也就是说2对一个数的补= -(该数的补)

所有这一切又产生了一个问题,为什么我们只能使用n位中的(n-1)来表示正数,为什么最左边的第n位表示符号(最左边的0表示+ve个数字,1表示-ve个数字)。例如,为什么我们在Java中只使用int的前31位来表示正数,如果第32位是1,它是-ve数。

 1100 (lets assume 12 in 4 bit system)
+0100(2's complement of 12)
___________________________

1 0000(结果为0,进位1溢出)

因此(n + 2'补n) = 0的方程组仍然成立。这里唯一的歧义是2对12的补码是0100,它也模糊地表示+8,而不是在2s补码系统中表示-12。

如果正数的最左边总是有一个0,这个问题就可以解决了。在这种情况下,它们的2的补位总是在最左边有一个1,我们就不会有相同的位集表示2的补位数和+ve数的模糊性。

我们对加减法都只做加法运算。我们将第二个操作数与第一个操作数相加。对于减法,我们将第二个操作数的2的补数与第一个操作数相加。

对于2的补码表示,我们不需要单独的数字组件,只使用加法器和补法器。