Fork me on GitHub

补码、反码、原码

补码、反码、原码这些都是计算机中的概念,这些概念的由来,跟计算机发展历史中实现减法操作有关!

早期的计算机先实现了加法机,为了实现减法操作,伟人们开始想着怎么实现一个减法机,但是他们想到,问题的产生往往是由复杂的根源引起,加法的“进位”操作已经让计算机实现加法机时遇到了挑战,减法有其“借位”操作,又将“头疼”一番了。伟人们的智慧简化了这个问题,减法可以通过加法的操作去实现,在计算机中我们就用加法机就能实现加法与减法操作了。关键在于“减法怎么通过加法的操作去实现”:

十进制的减法使用加法来实现

74-59=15,这是一个简单的十进制(两位数)减法例子,我们稍微将这个式子,表达式两边都加上100,再进行转换,表达式就等于
(1)74+100-59=100+15 -> (2) 74+1+99-59=1+99+15 -> (3) 75 + 40 = 100 +15 -> (4)115-100 =15
上面有关键的两点需要了解:
1、因为计算的两位数减法,所以式子两边相加的是100
2、把一个数从一串9中减去称为9的补数或补码(此补码非标题中的补码)
表达式转换到(2)时,发现这里面就一个减法,就是99-59=40,结合上面第二点,得出结论,40就是59相对于9的补数

40就是59相对于9的补数,有何意义?

当我们计算两位数减法的时候,我们将一个数用99减去,无论这个数是什么,它都不用做借位运算,这就是好处!比如99-98,99-12,99-42等等都不用进行借位。因为99已经是两位数减法中最大的一个两位数了。我们已经发现,有了这个,我们的借位问题被解决了

表达式(4)中不还是进行了减法了么?没完全用加法代替减法啊

是的,表达式(4)中115-100=15还是进行了减法,这个我们用二进制来解释

二进制中的减法使用加法来实现

表达式转成二进制74-59=15 -> (1)01001010(74)-00111011(59) = 00001111(15) -> (2)11111111(255) + 00000001(1) + 01001010(74) -00111011(59) = 11111111(255)+00000001(1) + 00001111(15) -> (3)11111111(255) - 00111011(59) + 00000001(1) + 01001010(74) = 11111111(255)+00000001(1) + 00001111(15)
表达式转成二进制,还是使用上面十进制同样的方式来将减法转换为加法,表达式两边都加上100000000=11111111+00000001,结合上述补数定义,得出结论表达式(3)中的11111111(255) - 00111011(59)=11000100(196)表示的是11000100(196)是00111011(59)相对于1的补数,1的补数也称为相反数或者反码,这就是反码的定义,即反码的计算方式

2的补数

2的补数就是1的补数再加上1,2的补数也被称为二进制中的补码,那么可以得出11000101(11000100+00000001)是00111011相对于2的补数,于是上述二进制计算的表达式可以用2的补数(补码)来计算,表达式转换为-> 01001010(74)-00111011(59) -> 01001010(74)+[11111111(255) -00111011(59) + 00000001(1)]->01001010+11000101,计算结果等于100001111,十进制为271,在此我们继续第四步运算,将100001111-100000000,结果等于00001111(15),结果是正确的,但是在计算机中,这第四步的二进制运算如果还是需要计算的话,那么减法操作还是没有避免啊?

溢位

上述运算中,1001010+11000101的运算产生了溢位,8位数运算结果为9位。我们需要进行减去9位的100000000,得到结果其实为000001111(9位),最后这个减法操作对于8位二进制相加来说,其实是多余的,因为8位二进制相加,所得到的溢位肯定是1,那么我们减去100000000,相当于是消去了首位的1,得到首位为0,首位为0对于结果来说没有意义。

计算机中存储负数

11000101是00111011相对于2的补数,那么我们计算两个数A与B相减的时候,相当于计算A+(-B)等于A+B的补码,既然是如此转换,计算机也是按这个转换逻辑去做的,负数在计算机中存储的是补码。这也就是为什么byte字节的取值范围为-128~127的原因。

原码

原码很好理解,就是原来的编码,比如1或-1,1的原码就是00000001,-1的原码是10000001,第一位代表符号位。10000001是不是存储在计算机中的-1的表示呢?不是,请记住,负数在计算机中是以补码的形式存储的,那么需要将原码转换为补码,转换过程如下:10000001(-1的原码)->11111110(-1的反码)->11111111(-1的补码),-1在计算机中是以11111111来存储的。

总结:

1、补码、反码、原码的由来都是因为计算机发展过程中,进行简化减法运算而诞生的
2、负数在计算机中是以补码的形式存储的

posted @ 2022-01-02 22:21  三脚半猫  阅读(376)  评论(0编辑  收藏  举报