在大学学习很多计算机课程时,第一章节总会遇到原码、反码、补码这哥仨,再后面就完全见不到了,当时只是跟着书上的方法去计算,也不知道这玩意算出来是干啥的,为什么要引入这哥仨。本文就是从说明原码、反码、补码的引入原因来解释这三个名词,所以介绍的顺序与大学课本有所不同,本文的介绍顺序是原码、补码、反码,望知悉。
一、背景
大家都知道,在计算机内部,数据都是以二进制的方式存储运算的,为什么采用二进制而不采用大家熟悉的十进制?因为二进制最简单、最好实现,只要一个事物具有两种对立状态都可以作为二进制思想的实现,比如使用元件开关特性、电压高低特性即可实现。
根据冯诺依曼提出的经典计算机体系结构框架。一台计算机由运算器,控制器,存储器,输入和输出设备组成。其中运算器,只有加法运算器,没有减法运算器(据说一开始是有的,后来由于减法器硬件开销太大,被废了 )
所以,计算机中是无法直接做减法的,它的减法是通过加法来实现的。你也许会说,现实世界中所有的减法也可以当成加法的,减去一个数,可以看作加上这个数的相反数。当然没错,但是前提是要先有负数的概念。这就为什么不得不引入一个该死的符号位。由此,人们发明了原码表示法。
二、原码表示法
1、计算方法
原码:用最高位表示符号位,‘1’表示负号,‘0’表示正号。其他位存放该数的二进制的绝对值。
2、说明
若以带符号的四位二进制数为例:
1010 : 最高位为‘1’,表示这是一个负数,其他三位为‘010’,即(0*2^2)+(1*2^1)+(0*2^0)=2(‘^’表示幂运算符)。所以1010表示十进制数(-2)。
下图给出部分正负数数的二进制原码表示法:
OK,原码表示法很简单有没有,虽然出现了+0和-0,但是直观易懂。
于是,我们高兴的开始运算。
0001+0010=0011 (1+2=3)OK
0000+1000=1000 (+0+(-0)=-0) 额,问题不大
0001+1001=1010 (1+(-1)=-2)
what? 1+(-1)=-2,逗我玩的吧?
如果采用原码表示法,看来是不能这样简单的做加法运算的,必须这样处理:当两数相加时,如果是同号则数值相加;如果是异号,则要进行减法。而在进行减法时,还要先比较绝对值的大小,然后大数减去小数,最后还要给结果选择恰当的符号。
如果这样去实现,太复杂了吧,有没有简单点的方法,于是人们找到了补码表示法。
三、补码表示法
1、实现思想
艺术源于生活
其实人类的很多发明创意都是来源于生活,例如鲁班根据有齿的小草发明了锯、意大利发明家博列里通过对鱼类的观察发明了潜水艇、科学家根据蜻蜓飞行结构研制出了直升飞机等等。补码的思想源于时钟的运动。
假设现在的标准时间为4点整,而有一只表已经7点了,为了校准时间,可以采用两种方法:一是将时针退7-4=3格;一是将是针向前拨12-3=9格。这两种方法都能对准到4点,由此看出,减3和加9是等价的。就是说9是(-3)对12的补码,可以用数学公式表示为:
-3 = +9 (mod 12)
mod 12的意思就是12为模数,这个“模”表示被丢掉的数值。上式在数学上称为同余式。
上例中之所以7-3和7+9(mod 12)等价,原国就是表指针超过12时,将12自动丢掉,最后得到16-12=4。
由此得到一个启发,就是负数用补码表示时,可以把减法转化为加法。这样,在计算机中实现起来就比较方便。
采用补码表示法进行减法运算比原码方便多了。因为不论数是正或负,机器总是做加法,减法运算可变成加法运算。但根据补码定义,求负数的补码还要做减法这显然不方便,为此可通过反码来解决。
2、计算方法
补码:正数的补码等于他的原码
负数的补码等于反码+1。(反码的知识见下一小节)
下图给出部分带符号位四位二进制的补码表示法
根据上面的补码图,我们可以做几道运算(下面运算中括号中为十进制):
0001(1)+ 1111(-1)= 0000(0)
1111(-1)+1110(-2)= 1101(-3)
至此,我们发现减法的问题解决了,正0、负0的问题也解决了,计算机可以很容易只通过加法来计算加减运算了。
四、反码表示法
1、计算方法
反码:正数的反码还是等于原码
负数的反码就是他的原码除符号位外,按位取反。
2、说明
反码的引入主要是为了解决计算一个负数的补码。
若以带符号的四位二进制数为例:
3是正数,反码与原码相同,则可以表示为0011
-3的原码是1011,符号位保持不变,低三位(011)按位取反得(100),所以-3的反码为1100
下图给出部分正负数的二进制数反码表示法
负数的反码加上这个负数的绝对值正好等于1111,再加1,就是1000,也就是四位二进数的模。而负数的补码是它的绝对值的同余数,可以通过模减去负数的绝对值,得到他的补码。
所以 负数的补码就是它的反码+1。
总结
1、原码的引入是由于计算机是采用二进制来运算和存储的,补码的引入主要是为了解决负数的运算的,而反码的引入是为了方便计算补码。
2、计算机中所有数据都是以补码的形式存储、计算的。