原码、反码、补码其实两年前就讲过,只是当时的理解太过肤浅或者直接说就是没有理解,因为对于数学比较发怵的我看到那么多的公式很是脑袋大,所以想要硬记也记不住。这次讲课的时候好歹知道了运算规则,但别人一问为什么,立马那个冏啊~好了,废话不多说了,开始进入正题(如果我的理解有偏差,恳请各位大虾不吝指出):
一张图胜过千言万语,下面的这张是本篇想要说的大概内容
我们知道,计算机是以0和1进行运算的,而且内部只有加法运算器,但日常生活中使用的却是十进制,并且有正负之分。于是我们发明了原码:最高位存放符号(正数用0表示,负数用1表示),其余为真值位。这样就可以方便的进行算术运算了。但很快,我们发现在进行加、乘、除的时候结果均正确,减法却出现了一些问题,下面举个例子:
假设计算机的字长为8 byte,那么
(2)D -(2)D = (2)D +(-2)D = (0)D D表示十进制
(00000010)原+(10000010)原=(10000100)原=(-4)D
以上结果用原码进行计算的显然不正确。因为正数计算的时候没有问题,那么肯定出现在负数身上,为了解决这个问题,我们引入了反码:对负数的原码符号位不变,真值位进行逐位取反。反码的运算如下:
(1)D-(2)D=(-1)D
(00000001)反+(11111101)反=(11111110)反=(10000001)原=(-1)D
而对于在原码中提到的十进制2-2=0的算法如下:
(00000010)反+(11111101)反=(11111111)反=(10000000)原=(-0)D
发现得到的结果是-0!而在我们的日常计算中,0是不分正负的。为了解决这个问题,我们引入了补码:对负数的补码真值位加1。如果最高位(符号位)有进位,则进位被舍弃。
在补码中用(-128)D代替了(-0),故补码的表示范围为(-128~0~127)共256个。需要注意的是:(-128)D没有对应的原码和反码。补码的十进制2-2=0的运算如下:
(00000010)补+(11111110)补=(00000000)补=(00000000)原=(0)D
可以发现补码的运算无误(大家感兴趣的话可以使用其他式子练习),因此,在计算机系统中,数值一律使用补码进行存储,它能将符号位和真值位统一进行处理。
但是我们不能高兴的太早,还有一个问题:大家有没有发现(-2)D的原码、反码、补码分别大于(2)D的原码、反码、补码?这跟我们日常的认知不相符,为了解决这个问题,我们引入了移码的概念(其实这个并不是移码的来历,只是为了好记一些而已):如果机器字长为n,规定数X上增加一个偏移量2n-1。那么,这个时候
[-2]移=27+(-2)D =(1000000)补+(11111110)补=(01111110)补
[2]移=27+(2)D =(10000000)补+(00000010)补=(10000010)补
[-2]移<[2]移
一张图看懂原码、反码、补码、移码,布布扣,bubuko.com
原文地址:http://blog.csdn.net/wlccomeon/article/details/25000705