我在上一门计算机系统课程,在某种程度上,我一直在为“二的补充”而挣扎。我想了解它,但我所读到的一切并没有让我明白它的含义。我读过维基百科的文章和其他各种文章,包括我的课本。
什么是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的补数的好处在于加法运算可以正常进行。你不需要做任何特殊的加法和负数!
其他回答
我在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的补语加一个额外的1时,我们将得到2的补语。例如:100101,它的1的补足是011010和2的补足是011010+1 = 011011(通过与1的补足相加) 本文以图解的方式对此进行了解释。
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)的混淆。
除非你的工作非常接近硬件,否则你可能不需要处理个位补或符号幅度整数表示。
想象一下,你有有限数量的比特/比特/数字等等。将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的多个表示形式 避免在溢出的情况下跟踪进位(如补位)。 进行简单的加法和减法运算变得很容易。