深刻理解原码,反码,补码的原理

深刻理解原码,反码,补码的原理

预备知识

二进制,十六进制,二进制与十进制的转化运算c++

根据冯诺依曼结构的运算器,只有加法运算器,没有减法运算器算法

因此,计算机中不是直接作减法,是经过加法来实现的。因此就必须引入一个符号位设计

原码,反码,补码 的产生就是为了解决这个问题3d

原码

最简单的机器数表示法code

原码:blog

最高位表示符号位,1表示负,0表示正class

其余位存放该数的二进制的绝对值基础

img

直接用原码运算原理

0001+0010=0011    (1+2=3)正确
0000+1000=1000    ((+0)+(-0)=-0)
0001+1001=1010    (1+(-1)=-2)出错
1001+1001= ?

原码正数之间的加法一般不会出错硬件

正数与负数相加,或负数与负数相加,问题就出现了

因此,原码直观易懂,易于正值转换,但用来实现加减法的话,运算规则总归是太复杂,因而反码来了

反码

原码最大的问题就在于一个数加上他的相反数不等于零,反码的设计思想就是为了解决这一点

反码:

正数的反码=原码

负数的反码=原码除符号位外,按位取反

图片描述

咱们试着用反码运算

0001+1110=1111 (1+(-1)=(-0))  有点问题,也正确
1110+1101=1011 (-1)+(-2)=(-4) 两个负数相加,出错

负数相加出错,问题不大,咱们只须要在两个负数相加时,将两个负数反码包括符号位所有按位取反相加,而后再给他的符号位强置‘1’就能够了。

反码表示法其实已经解决了减法的问题,他不只不会像原码那样出现两个相反数相加不为零的状况,并且对于任意的一个正数加负数,计算结果是正确的

而后就有了补码

补码

补码:

正数的补码=原码

负数的补码=反码+1

负数的补码的另一种算法:

自低位向高位,尾数第一个1及其右部的0保持不变,左部取反,符号位不变

其实上面两段话,都只是补码的求法,而不是补码的定义,基础工做者并不会心血来潮的把反码+1就定义为补码,只不过是补码正好就等于反码加1罢了

暂时先忘记书上那句负数的补码等于它的反码+1,咱们的理解陷入了误区

这也是为何《计算机组成原理》要**特地先讲补码,再讲反码

接下来咱们要重点讲讲补码的思想

补码的思想

为了理解,先得引入同余的思想

其实就是一个计量器的容量大小,好比钟表的模M=12

同余 是指两个整数A和B除以同一个正整数M,所得余数相同,好比1点和13点,2点和14点就是同余的,能够写做

1 = 13 mod (12), 2 = 14 mod (12)

若是说如今时针如今停在10点钟,那么何时时针会停在8点钟呢?

这么说吧,由于过去2个小时前是8点,因此将来10个小时候也是8点

也就是说:倒拨2小时 或 正拨10小时 都是八点钟

10-2=8,(10+10)mod(12)=8

因此,10-2和10+10从另外一个角度来看是等效的,它都使时针指向了8点钟

既然是等效的,那在时钟运算中,减去一个数,其实就至关于加上另一个数(这个数与减数相加正好等于12,也就是同余数)

我再次强调,原码,反码,补码的引入是为了解决作减法的问题。在原码,反码表示法中,咱们把减法化为加法的思惟是减去一个数,等于加上一个数的相反数,结果因为引入符号位形成了各类问题

那你应该知道我要说什么了,利用模和同余的概念,咱们能够使减法运算转化为加法运算

而如今,咱们不引入负数的概念,就能够把减法当成加法来算

因此接下来咱们聊4位二进制数的运算,也没必要急于引入符号位。由于补码的思想,把减法当成加法时并非必需要引入符号位的。

并且咱们能够经过下面的例子,也许能回答另外一个问题,为何负数的符号位是‘1’,而不是正数的符号位是‘1’

四位二进制补码运算实例

0110 - 0010 (6-2=4) 计算机中没有减法器,不能直接算

可是如今你知道,减去一个数,能够等同于加上另一个正数(同余数)

那么这个数是什么呢?时钟运算中咱们能够看出这个数与减数相加正好等于模M=12

四位二进制数的(计量器)=四位二进制数最大容量=2^4=16=10000B

那么2(0010)的同余数,就等于10000-0010=1110(14)

既然如此

0110(6) - 0010(2) = 0110(6) + 1110(14) = 10100(16+4=20)

OK,咱们看到按照这种算法得出的结果是10100,可是对于四位二进制数,最大只能存放4位(硬件决定),正好是0100(4),就是咱们想要的结果,至于最高位的1,计算机会把他放入psw寄存器进位位中。8位机则会放在cy中,x86会放在cf中(不做讨论)

这个时候,咱们再想一想在四位二进制数中,减去2,就至关于加上它的同余数14

可是减去2,从另一个角度来讲,也是加上(-2)。即加上(-2)和加上14其实获得的二进制结果除了进位位,结果是同样的。

若是咱们把1110(14)的最高位看做符号位后就是(-2)的补码,这可能也是为何负数的符号位是‘1’而不是‘0’,

并且在有符号位的四位二进制数中,能表示的只有‘-8~7’,而无符号位数(14)的做用和有符号数(-2)的做用效果实际上是同样的。

那正数的补码呢?加上一个正数,加法器就直接能够实现。因此它的补码就仍是它自己。

图片描述

到这里,咱们发现原码,反码的问题,补码基本解决了。

作减法时,0001(1)+1111(-1)=0000,咱们不再须要一个1000来表示负0了,就把1000规定为-8

负数与负数相加的问题也解决了1111(-1)+1110(-2)=1101(-3)

为何能够+1

而后咱们再来看看为何负数的补码的求法为何是反码+1

由于负数的反码加上这个负数的绝对值正好等于1111,再加1,就是1000,也就是四位二进数的模

而负数的补码是它的绝对值的同余数,能够经过模减去负数的绝对值,获得他的补码。

因此,负数的补码就是它的反码+1

算补码的小技巧

若是咱们把-8当成负数的原点。那么-5的补码是多少呢?

-5 = -8 + 3

-5的补码就是-8的补码加3

1000(-8) + 0011(3) = 1011(-5)

也能够记住-1的补码是1111口算减法得出

1111(-1) - 0100(4) = 1011(-5)

对于八位加法器的话,能够把-128当补码原点。十六位能够把-32768当补码原点。

是的,128256(八位二进制数的模)的一半,3276865536(十六位二进数的模)的一半

也很方便有没有,并且简单的是

补码原点老是最高位是‘1’,其余位是‘0’

感谢阅读

相关文章
相关标签/搜索