原码、反码、补码

                     

贡献者: lzq; addis

1. 原码(True form)

   原码即 “未经更改” 的码,是指一个二进制数左边加上符号位后所得到的码,且当二进制数大于 $0$ 时,符号位为 0;二进制数小于 $0$ 时,符号位为 $1$;二进制数等于 $0$ 时,符号位可以为 $0$ 或 $1$(表示 $+0$ 或 $-0$)。

   使用 $n$ 位原码表示有符号数时,范围是 $-(2^{n-1}-1)$ 到 $+(2^{n-1}-1)$。当 $n=8$ 时,第一位用于符号位,这个范围就是 $-127\sim +127 $;表示无符号数时,由于不需要考虑数的正负,就不需要用一位来表示符号位,$n$ 位机器数全部用来表示是数值,这时表示数的范围就是 $0\sim 2^{n}-1$。当 $n=8$ 时,这个范围就是 $0\sim 255$。

   优点: 简单直观,原码易于人类理解和计算(与真值转换容易)。

   缺点:原码不能用无符号的加法器进行运算。例如,数学上,$1+(-1)=0$,但把原码直接进行无符号的加法运算时(即把两个相加的数都视为 $0-255$ 的整数相加):

\begin{equation} 00000001 + 10000001=10000010~. \end{equation}
该结果对应数值为 $-2$。显然出错了; 对于减法运算,原码减法需要先将减数取反加 $1$,才能得到正确的数学结果。

   也就是说:原码的运算,必须将符号位和其他位分开,这就增加了硬件的开销和复杂性。也有人将该符号问题称作正负 $0$ 现象。

2. 反码(1's complement)

   我们发现:原码最大的问题就在于一个数加上它的相反数不等于 $0$,于是反码的设计思想就是冲着解决这一点,既然一个负数是一个正数的相反数,那干脆用一个正数按位取反来表示负数。

   在反码表示法中,正数和 $0$ 的反码与其原码相同;负数的反码则是将原码(除符号位外)的每一位取反。

   缺点: 虽然解决了相反数相加不等于 $0$ 的问题,但是反码不能直接做减法,并且存在多余的负零(eg. 1111_1111)

例 1 

   0001+1110=1111,1+(-1)=-0;

   1110+1100=1010,(-1)+(-3)=-5。

3. 补码(2's complement)

   正数和 $0$ 的补码就是该数字本身再补上最高比特 $0$。负数的补码则是将其绝对值按位取反再加 $1$。

   优点: 在实现加法器时,只要一种加法电路就可以处理各种有号数加法,因为减法可以用一个数加上另一个数的补码来表示,因此只要有加法电路及补码电路即可完成各种有号数加法及减法,在电路设计上相当方便。(实际在加法器做减法运算时,只需要让减数通过非门,并让个位的 “进位” 端口从 $0$ 变为 $1$ 即可)

   另外,补码系统的 $0$ 就只有一个表示方式,这和反码系统不同(在反码系统中,$0$ 有两种表示方式),因此在判断数字是否为 $0$ 时,只要比较一次即可。

4. 补码的设计

   补码的规则看起来很怪,我们可以换一种角度理解:

   在设计一个编码时,我们可以把编码后的数围成一个圆(类似一个时钟),我们希望在这个钟表上:

  1. 无冲突,每个数值的位置都是独一无二,有唯一的 $0$。
  2. 连续性,每次运算($+1$)相当于时钟顺时针移动一个单位,尤其是从最大的正数加 $1$ 会 “溢出” 到最小的负数,这种看似异常的行为实际上提供了一个连续且循环的数值范围,使得算术运算能够在这个编码系统中顺畅地进行。

   从上述角度看,补码是一种很和谐的编码。

5. 补码的总结

   对 $N$ bit 的有符号整数,如果用补码表示负整数,则:


致读者: 小时百科一直以来坚持所有内容免费无广告,这导致我们处于严重的亏损状态。 长此以往很可能会最终导致我们不得不选择大量广告以及内容付费等。 因此,我们请求广大读者热心打赏 ,使网站得以健康发展。 如果看到这条信息的每位读者能慷慨打赏 20 元,我们一周就能脱离亏损, 并在接下来的一年里向所有读者继续免费提供优质内容。 但遗憾的是只有不到 1% 的读者愿意捐款, 他们的付出帮助了 99% 的读者免费获取知识, 我们在此表示感谢。

                     

友情链接: 超理论坛 | ©小时科技 保留一切权利