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

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


当前回答

2的补码对于查找二进制值非常有用,但是我想到了一个更简洁的方法来解决这样的问题(从未见过其他人发布它):

以二进制为例:1101(假设空格“1”是符号)等于-3。

使用2的补码,我们可以这样做…翻1101到0010…加上0001 + 0010 ===>得到0011。0011的正二进制= 3。因此1101 = -3!

我意识到:

而不是所有的翻转和加法,你可以只做一个基本的方法来解决正二进制(假设0101)是(23 * 0)+(22 * 1)+(21 * 0)+(20 * 1)= 5。

用否定句做同样的概念!(稍微扭曲一下)

以1101为例:

对于第一个数字,用-(23 * 1)= -8代替23 * 1 = 8。

然后像往常一样,做-8 + (22 * 1)+ (21 * 0)+ (20 * 1)= -3

其他回答

我在Reddit上读到jng的一篇精彩的解释,用里程表做类比。

It is a useful convention. The same circuits and logic operations that add / subtract positive numbers in binary still work on both positive and negative numbers if using the convention, that's why it's so useful and omnipresent. Imagine the odometer of a car, it rolls around at (say) 99999. If you increment 00000 you get 00001. If you decrement 00000, you get 99999 (due to the roll-around). If you add one back to 99999 it goes back to 00000. So it's useful to decide that 99999 represents -1. Likewise, it is very useful to decide that 99998 represents -2, and so on. You have to stop somewhere, and also by convention, the top half of the numbers are deemed to be negative (50000-99999), and the bottom half positive just stand for themselves (00000-49999). As a result, the top digit being 5-9 means the represented number is negative, and it being 0-4 means the represented is positive - exactly the same as the top bit representing sign in a two's complement binary number. Understanding this was hard for me too. Once I got it and went back to re-read the books articles and explanations (there was no internet back then), it turned out a lot of those describing it didn't really understand it. I did write a book teaching assembly language after that (which did sell quite well for 10 years).

这是一种对负整数进行编码的聪明方法,该方法将数据类型中大约一半的位组合保留给负整数,并且将大多数负整数与其对应的正整数相加会导致进位溢出,使结果为二进制零。

因此,在2的补码中,如果1是0x0001,那么-1是0x1111,因为这将导致0x0000的组合和(溢出1)。

我喜欢lavinio的回答,但变换部分增加了一些复杂性。通常情况下,可以选择在保留符号位的情况下移动位,或者不保留符号位。这是将数字处理为有符号数字(-8到7表示小块,-128到127表示字节)或全范围无符号数字(0到15表示小块,0到255表示字节)之间的选择。

问题是“什么是“2的补码”?”

对于那些想要从理论上理解它的人(以及我试图补充其他更实际的答案),简单的答案是:2的补码是对偶系统中不需要额外字符(如+和-)的负整数的表示。

就像我看到的大多数解释一样,上面的解释清楚地说明了如何使用2的补码,但并没有真正解释它们在数学上是什么。我会试着这么做,至少对整数来说是这样的,我会先介绍一些你们可能熟悉的背景知识。

回想一下它是如何用于十进制的:2345是2 × 103 + 3 × 102 + 4 × 101 + 5 × 100的一种写法。

同样地,二进制是一种只使用0和1来写数字的方法,遵循相同的思路,但把上面的10换成了2。然后在二进制中,1111是1 × 23 + 1 × 22 + 1 × 21 + 1 × 20的一种写法,如果你算出来,结果等于15(以10为底)。因为8+4+2+1 = 15。

这对于正数来说很好。它甚至适用于负数,如果你愿意在负数前面加一个负号,就像人类对待小数一样。在某种程度上,这甚至可以在计算机上完成,但我从20世纪70年代初就没见过这样的计算机了。我将把原因留到另一个讨论。

对于计算机来说,负数使用补表示法效率更高。这里有一些经常被忽视的东西。补表示法涉及到数字数字的某种反转,甚至是在正常正数之前隐含的零。这很尴尬,因为问题来了:所有这些?这可能是一个无限的数字要考虑。

幸运的是,计算机并不代表无穷。数字被限制在特定的长度(或者宽度,如果你喜欢)。所以让我们回到正二进制数,但有一个特定的大小。在这些例子中,我将使用8个数字(“位”)。所以我们的二进制数应该是00001111或者0 × 27 + 0 × 26 + 0 × 25 + 0 × 24 + 1 × 23 + 1 × 22 + 1 × 21 + 1 × 20

为了形成2的补负,我们首先将所有的(二进制)数字补成11110000,然后加上1,形成11110001,但我们如何理解这意味着-15?

The answer is that we change the meaning of the high-order bit (the leftmost one). This bit will be a 1 for all negative numbers. The change will be to change the sign of its contribution to the value of the number it appears in. So now our 11110001 is understood to represent  -1 × 27 + 1 × 26 + 1 × 25 + 1 × 24 + 0 × 23 + 0 × 22 + 0 × 21 + 1 × 20Notice that "-" in front of that expression? It means that the sign bit carries the weight -27, that is -128 (base 10). All the other positions retain the same weight they had in unsigned binary numbers.

算出-15,就是-128 + 64 + 32 + 16 + 1用计算器试试。它是-15。

Of the three main ways that I've seen negative numbers represented in computers, 2's complement wins hands down for convenience in general use. It has an oddity, though. Since it's binary, there have to be an even number of possible bit combinations. Each positive number can be paired with its negative, but there's only one zero. Negating a zero gets you zero. So there's one more combination, the number with 1 in the sign bit and 0 everywhere else. The corresponding positive number would not fit in the number of bits being used.

关于这个数字更奇怪的是,如果你试图通过互补和加1来形成正数,你会得到相同的负数。0会这样做似乎很自然,但这是出乎意料的,完全不是我们习惯的行为,因为除了计算机,我们通常认为数字是无限供应的,而不是这种固定长度的算术。

这只是怪胎的冰山一角。表面之下还有更多的东西在等待着,但这就足够我们讨论了。如果你研究定点算术中的“溢出”,你可能会发现更多。如果你真的想深入了解它,你可能还会研究“模算术”。