我在上一门计算机系统课程,在某种程度上,我一直在为“二的补充”而挣扎。我想了解它,但我所读到的一切并没有让我明白它的含义。我读过维基百科的文章和其他各种文章,包括我的课本。
什么是2的补数,我们如何使用它,它如何在强制转换(从有符号到无符号,反之亦然)、逐位操作和位移位操作等操作中影响数字?
我在上一门计算机系统课程,在某种程度上,我一直在为“二的补充”而挣扎。我想了解它,但我所读到的一切并没有让我明白它的含义。我读过维基百科的文章和其他各种文章,包括我的课本。
什么是2的补数,我们如何使用它,它如何在强制转换(从有符号到无符号,反之亦然)、逐位操作和位移位操作等操作中影响数字?
当前回答
两人的补足(托马斯·芬利)
我把所有位的倒数加1。编程:
// In C++11
int _powers[] = {
1,
2,
4,
8,
16,
32,
64,
128
};
int value = 3;
int n_bits = 4;
int twos_complement = (value ^ ( _powers[n_bits]-1)) + 1;
其他回答
让我们用8位的二进制形式得到答案10 - 12: 我们要做的是10 + (-12)
我们需要用12的恭维部分减去10。 12的二进制值是00001100。 10的二进制值是00001010。
为了得到12的赞美部分,我们只需要把所有的位反转,然后加1。 12的二进制反转是11110011。这也是逆码(一个人的补码)。 现在我们需要加一个,现在是11110100。
所以11110100是12的赞美!这样想很简单。
现在你可以用二进制形式来解决上面的10 - 12问题了。
00001010
11110100
-----------------
11111110
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
问题是“什么是“2的补码”?”
对于那些想要从理论上理解它的人(以及我试图补充其他更实际的答案),简单的答案是:2的补码是对偶系统中不需要额外字符(如+和-)的负整数的表示。
简单来说,2的补码是一种在计算机内存中存储负数的方法。而正数则存储为普通二进制数。
让我们考虑这个例子,
计算机使用二进制数字系统来表示任何数字。
x = 5;
这表示为0101。
x = -5;
当计算机遇到-号时,它会计算出它的2的补数并存储它。
也就是说,5 = 0101,它的2的补是1011。
计算机处理数字的重要规则是,
如果第一位是1,那么它一定是负数。 如果除第1位之外的所有位都是0,那么它就是一个正数,因为在数字系统中没有-0(1000不是-0,而是正8)。 如果所有的位都是0,那么它就是0。 否则就是正数。
我在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).