原码、反码、补码的理解

概念

机器数、真值

  • 机器数

一个数在计算机中的二进制表示形式,叫做这个数的机器数。机器数是带符号的,在计算机用机器数的最高位存放符号,正数为0,负数为1。

比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是0000 0011。如果是 -3 ,就是 100 00011 。

那么,这里的 0000 0011 和 1000 0011 就是机器数。

  • 真值

因为第一位是符号位,所以机器数的形式值就不等于真正的数值。

例如上面的有符号数 1000 0011,其最高位1代表负,其真正数值是 -3,而不是形式值131(1000 0011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

原码、反码、补码

原码、反码、补码是机器存储一个具体数字的编码方式。机器数包含了原码、反码、补码的表示形式。

  • 原码

原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值。比如:如果是8位二进制:

[+1]原= 0000 0001

[-1]原= 1000 0001

第一位是符号位,因为第一位是符号位,所以8位二进制数的取值范围就是:(即第一位不表示值,只表示正负。)

[1111 1111 , 0111 1111]

[-127 , 127]

  • 反码

反码的表示方法是:

正数的反码是其本身;

负数的反码是在其原码的基础上,符号位不变,其余各个位取反。

[+1] = [0000 0001]原= [0000 0001]反

[-1] = [1000 0001]原= [1111 1110]反

可见如果一个反码表示的是负数,人脑无法直观的看出来它的数值。通常要将其转换成原码再计算。

反码表示在计算机中往往作为数码变换的中间环节。

  • 补码

补码的表示方法是:

正数的补码就是其本身;

负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1。(也即在反码的基础上+1)

[+1] = [0000 0001]原= [0000 0001]反= [0000 0001]补

[-1] = [1000 0001]原= [1111 1110]反= [1111 1111]补

对于负数,补码表示方式也是人脑无法直观看出其数值的。通常也需要转换成原码再计算其数值。

为什么用反码和补码

计算机辨别”符号位”显然会让计算机的基础电路设计变得十分复杂,所以要把对于负数的减法运算转成加法运算。

将钟表想象成是一个1位的12进制数。例如钟表上的时间为6点,如果我们希望将时间设置为4点,那么我们可以将钟表往回拨2个小时,即“-2”,或者我们可以将钟表往前拨10个小时,即“+10”

  1. 往回拨2个小时:6 - 2 = 4
  2. 往前拨10个小时:(6 + 10)mod 12 = 4

这样就将减法计算转成了加法计算。

类似钟表,计算机中的数值也是有一定范围的,所以同样可以将计算机中的减法运算改为加法运算,即将真值为负的机器数转为补码形式再做加法,实际上是将负数转换成了这个它的同余数(概念自行百度)

补码举例:

2-1 = 2+(-1) = [0000 0010]原+ [1000 0001]原= [0000 0010]补 + [1111 1111]补

如果把[1111 1111]当成原码,去除符号位,则[0111 1111]原 = 127

相当于

2-1 ≡ 2+127 (mod 128)

到底什么是补码

所以到底什么是补码?

其实负数的补码等于反码+1只是补码的求法,而不是补码的定义,很多人以为求补码就要先求反码,其实并不是,那些计算机学家并不会心血来潮的把反码+1就定义为补码,只不过补码正好就等于反码+1而已。

其实负数的补码,是能够和其相反数相加通过溢出从而使计算机内计算结果变为0的二进制码。这是补码设计的初衷,具体目标就是让1+(-1)=0,这利用原码是无法得到的:

0001(1) + 1001(-1) = 1010(-2)

而在补码中:

0001(1补) + 1111(-1补) = 10000(1溢出)

所以对于一个n位的负数-X,有如下关系

X + (-X) = 100…0(n个0) = 2^n^

假设寄存器是n位的,那么-X的补码应该是2^n^ - X的二进制编码

例如:

X = - 0b11(-3) ,四比特表示原码 = 1011(11),对应反码为 = 1100(12),补码为1101(13);
如果寄存器4位,-3对应的补码二进制数为13,刚好是2^4^-3

正十进制数X补码等于其本身,n位寄存器下-X的补码等于2^n^-X对应的二进制编码。

已知补码如何求原码

二进制

补码的补码就是原码

十进制

n位寄存器下-X的补码等于2^n^-X对应的二进制编码。

(1)十进制的情况下,如果给的补码是无符号数2^n^-X,那么原码即(2^n^-X) - 2^n^ = -X:
例如前面-3补码无符号数是13,对应的原码就是13-2^4^=-3

(2)十进制的情况下,如果给的补码是有符号数-Y,对应的无符号数就是2^n-1^ + Y,那么原码就是(2^n-1^ + Y)- 2^n^=Y-2^n-1^:
例如前面-3补码有符号数是-5,对应的原码就是5-2^3^ = -3

参考

原码、反码、补码
二进制的原码、反码、补码
补码的计算方法


原码、反码、补码的理解
https://fattree.cn/2023/02/08/原码、反码、补码的理解/
作者
fattree
发布于
2023年2月8日
许可协议