我在上一门计算机系统课程,在某种程度上,我一直在为“二的补充”而挣扎。我想了解它,但我所读到的一切并没有让我明白它的含义。我读过维基百科的文章和其他各种文章,包括我的课本。

什么是2的补数,我们如何使用它,它如何在强制转换(从有符号到无符号,反之亦然)、逐位操作和位移位操作等操作中影响数字?


当前回答

2's complement is essentially a way of coming up with the additive inverse of a binary number. Ask yourself this: Given a number in binary form (present at a fixed length memory location), what bit pattern, when added to the original number (at the fixed length memory location), would make the result all zeros ? (at the same fixed length memory location). If we could come up with this bit pattern then that bit pattern would be the -ve representation (additive inverse) of the original number; as by definition adding a number to its additive inverse always results in zero. Example: take 5 which is 101 present inside a single 8 bit byte. Now the task is to come up with a bit pattern which when added to the given bit pattern (00000101) would result in all zeros at the memory location which is used to hold this 5 i.e. all 8 bits of the byte should be zero. To do that, start from the right most bit of 101 and for each individual bit, again ask the same question: What bit should I add to the current bit to make the result zero ? continue doing that taking in account the usual carry over. After we are done with the 3 right most places (the digits that define the original number without regard to the leading zeros) the last carry goes in the bit pattern of the additive inverse. Furthermore, since we are holding in the original number in a single 8 bit byte, all other leading bits in the additive inverse should also be 1's so that (and this is important) when the computer adds "the number" (represented using the 8 bit pattern) and its additive inverse using "that" storage type (a byte) the result in that byte would be all zeros.

 1 1 1
 ----------
   1 0 1
 1 0 1 1 ---> additive inverse
  ---------
   0 0 0

其他回答

2的补码是表示负数的一种方式,大多数控制器和处理器都以2的补码形式存储负数。

想象一下,你有有限数量的比特/比特/数字等等。将0定义为所有数字都为0,并自然向上计数:

00
01
02
..

最终你会溢出。

98
99
00

我们有两位数字,可以表示从0到100的所有数字。所有这些数字都是正数!假设我们也想表示负数?

我们真正拥有的是一个循环。2之前的数字是1。1之前的数字是0。0之前的数字是…99.

为了简单起见,我们设任何大于50的数都是负数。0 ~ 49代表0 ~ 49。“99”是-1,“98”是-2,…“50”是-50。

这个表示是十的补数。计算机通常使用2的补码,除了使用位而不是数字之外,它是一样的。

10的补数的好处在于加法运算可以正常进行。你不需要做任何特殊的加法和负数!

Two的补码是一种存储整数的聪明方法,因此常见的数学问题很容易实现。

为了理解,你必须把数字想象成二进制。

它基本上是说,

对于0,用所有的0。 对于正整数,开始计数,最大值为2(位数-1)-1。 对于负整数,做完全相同的事情,但是切换0和1的角色并开始倒数(所以不是从0000开始,而是从1111开始——这是“补”部分)。

让我们尝试一个4位的迷你字节(我们称之为1/2个字节)。

0000 -零 0001 - 1 0010 - 2 0011 - 3 0100到0111,4点到7点

这是我们目前能找到的阳性结果。23-1 = 7。

负面影响:

1111 - 1 1110 - 2 1101 - 3 1100到1000 - - 4到- 8

注意,负数(1000 = -8)有一个额外的值,而正数没有。这是因为0000用于表示零。这可以看作是计算机的数轴。

区分正数和负数

这样一来,第一个位就扮演了“符号”位的角色,因为它可以用来区分非负的十进制值和负的十进制值。如果最高有效位是1,那么二进制就可以说是负的,如果最高有效位(最左边)是0,就可以说十进制值是非负的。

“符号量级”的负数只是将它们的正数对应的符号位颠倒了,但这种方法必须处理将1000(一个1后面跟着所有的0)解释为“负零”,这是令人困惑的。

“1的补”负数只是它们的正数的位补,这也导致了“负零”和1111(都是1)的混淆。

除非你的工作非常接近硬件,否则你可能不需要处理个位补或符号幅度整数表示。

2对给定数的补数是1与1的补数相加得到的数。

假设我们有一个二进制数:10111001101

它的1的补位是:01000110010

它的2的补数是:01000110011

按位补一个数就是将其中的所有位翻转。对2的补位,我们翻转所有的位,加1。

对有符号整数使用2的补码表示,我们应用2的补码操作将正数转换为负数,反之亦然。因此,以nibbles为例,0001(1)变成1111(-1),并再次应用该操作,返回0001。

零处操作的行为有利于给出零的单一表示,而无需特别处理正零和负零。0000与1111互补,当1111加1时。溢出到0000,得到一个0,而不是一个正1和一个负1。

这种表示的一个关键优点是,用于无符号整数的标准加法电路在应用于它们时产生正确的结果。例如,在nibbles中添加1和-1:0001 + 1111,比特溢出寄存器,留下0000。

作为一个温和的介绍,优秀的Computerphile制作了一个关于这个主题的视频。