理解原码、反码和补码

Understand the Original code、 Inverse code and Complement code

Posted by alovn on September 12, 2021

原码

如果我们在内存中分配4位(bit)来存放无符号的数字,它就是下面这样子的:

十进制二进制(4位)
00000
10001
20010
30011
40100
50101
60110
70111

数字是一个抽象的概念,生活中为了表示欠别人钱这个概念,就产生了正数和负数。

为了表示正数和负数,就发明了『原码』。把左边第一位用来存放符号位,0表示正数,1表示负数:

十进制原码(正数4位)十进制原码(负数4位)
00000-01000
10001-11001
20010-21010
30011-31011
40100-41100
50101-51101
60110-61110
70111-71111

原码的存储方式方便人类查看,但是却苦了计算机。

我们知道(+1)和(-1)相加是0,但是计算机若用原码相加就会算出:0001 + 1001 = 1010,十进制就是-2。这不是我们想要的结果。而且还有另外一个问题,这里有一个(+0)和(-0)。

反码

为了解决正负相加等于0的问题,在原码的基础上,又发明了『反码』。

反码是用来处理负数问题的,它的符号位置和原码一样不变,但是其它位置相反:

十进制反码(正数4位)十进制反码(负数4位)
00000-01111
10001-11110
20010-21101
30011-31100
40100-41011
50101-51010
60110-61001
70111-71000

使用反码代替原码,则解决了正负数相加等于0的问题。

(+1) + (-1) =0001 + 1110 = 1111,在反码中1111表示-0。

但是上面还提到一个问题:同时有两个零存在,+0和-0。

补码

精益求精的人类希望只有一个零存在,于是有发明了『补码』。补码同时解决了正负数相加等于0,和解决同时存在两个零的问题。

补码是在反码的基础上,补充了一个新的代码:将负数的反码+1。

十进制补码(正数4位)十进制补码(负数4位)
00000-00000
10001-11111
20010-21110
30011-31101
40100-41100
50101-51011
60110-61010
70111-71001

反码中的(-0)即1111再加上1后,就变成了10000。有得就有失,此时丢掉最高位就得到了0000,刚好得到了0。

这样就解决了正负数相加等于0的问题,同时也解决了(+0)和(-0)同时存在的问题。

对于在计算机中正负数的存储与计算方式,不断改进后,最终选择了『补码』的方案。

总结:原码是为了方便人类查看,反码过渡的中间产物。计算机实际使用中用来运算和存储的都是补码。