一篇文章了解补码

补码的作用:

为了方便cpu进行有符号整数间的加法运算,将它用补码表示,它的运算也用补码运算。

所以如果你有一个有符号整形变量,你要是去内存中查看它的值,你会发现它是以补码表示的二进制数,当然其他类型的变量,比如浮点数,用其他的规则表示。

但在这之前,人们就已经用原码来表示这些数了。

 

原码:

最高位为符号位,其余位为数值位。

其中符号位为0表示符号为正,为1则为负。

例如八位的原码:(下划线仅用于分割)

-1的原码:1000_0001

1的原码:0000_0001

 

原码对人来说非常好读,也非常好写。但补码却稍显麻烦。

 

对于正数,补码与原码一致,好书写。对于0也很简单,全为0即可。但对于负数,却要绕一个弯,对于原码,要想表示负数,太简单了,比如-1,我只需要在符号位写上1,在数值位表示1即可。但对于补码,负数往往不好直接写出,而是通过负数的原码变换出来,比如-1,这里以八位为例。

 

第一步,先写出-1的原码即1000_0001

第二步,数值位都取反,得到1111_1110,我们把这个叫反码。

第三部,将反码加一,得到补码1111_1111

 

经过这三步走,才得到了-1的补码。但看他的样子平平无奇,让人不禁怀疑,这个补码真的表示-1吗,所以我们将它与补码表示的1来相加看看等不等于0:

  1的补码: 0000_0001

-1的补码: 1111_1111

相加结果:1_0000_0000

我们发现结果超出了8位,进了一个1,这个结果显然不是0,但在实际运算过程中,由于储存运算结果的空间有限,它的位数往往和加数,被加数一致,这里就是8位,结果也只会保留8位,在这里也就只保留了低八位的0,在补码中,全部位都为0时表示的就是0,结果正确,-1+1=0。

 

既然一个数加上1等于0,那么这个数就是-1无疑了,虽然这个-1的补码看上去很奇怪,但实际上却是人们深思熟虑的结果,人们利用了储存结果有限这个不足,巧妙地表示了负数。

 

//补充补码表示负数的原理:

(在实际中,最高位进位了1这个信息会在运算结束后保留在标志位寄存器中。而且,运算的储存结果有限,相当于在每次运算结束后都有一个取模操作,使结果永远不可能比模大,这里的模是1_0000_0000。在生活中,一个时刻的时分秒中的分不可能大于60,这个60相当于模,凡是会取模的值都有一个特点,他能将减法运算变为加法运算,加法运算变为减法运算,比如分钟40,它+20和-40的结果是一样的,都等于0,我们就能把根据这个规律将减法变为加法,如果一个值a总是在运算后取模,那么有这样一个规律:a-b=a+(模-b),把之前的a等于40,b=20,模等于60代入这个等式,结果正确的。实际上补码也是利用这个等式,在那里我们的模是二进制的1_0000_0000,利用这个等式,可以将左边的减法变为右边的加法运算,但是右边的(模-b)怎么不用减法得到呢,很简单,对b所有位取反得到!b,再加上1即可,因为b+!b的结果全部位都为1,即八位都为1,再加上1就会进位得到模,即b+!b+1=模,将这个等式等价变换可以得到!b+1=模-b,所以只需要对b全部位取反再加1即可得到右边的加数。知道这个加数,那么就能将左边的减法变为右边的加法了。)

 

正数的补码:

正数的补码与原码一致。

 

0的补码:

所有位全为0

 

负数的补码:

三步走得到:写负数原码,数值位全部取反得到反码,加1得到补码。

-1的原码:1000_0001

-1的反码 :1111_1110

-1用补码:1111_1111

 

 

补码的好处:

在用补码表示数的时候,又发现一个好处,这里以八位码为例,原先用原码表示数的时候,我们可表示的数的范围是-127~127。

(当符号位为正时,结合剩下7个数值位能表示的范围是+0~127,当符号为负时,范围则是-127~-0,他们合起来就是-127~127)

 

对于原码来说,

1000_0000表示0

0000_0000也表示0,

(分正负意义不大,从数值上来说都一样)

 

但对于补码来说,

1000_0000表示-128

0000_0000才表示0

(为什么它表示-128?可以试试将它与补码表示的127相加,你会发现结果的补码表示-1)

这样下来,除了-128和0,八位补码还能表示正数0000_0001(1)~0111_1111(127),还能表示负数1000_0001(-127)~1111_1111(-1),补码能够表示的范围就成了-128~127,同样的位数,在方便CPU计算的同时,还比原码能多表示一个数,还有额外收获。

 

如何阅读补码:

那么对于补码,怎么一眼看出它所代表的值呢,按照补码的规则,可以总结出:

1:如果补码全部位都为0,那么它代表0

2:如果最高位是0,那么这个补码代表一个正数,且数值等于剩余位所代表的值

3.1:如果最高位是1,那么它表示一个负数,如果剩余位还全部为0,那么他代表这个补码能表示的最小的数,其绝对值等于2的n-1次方,n表示这个补码的位数,

3.2:如果最高位是1,那么它表示一个负数,如果剩余位不全部为0,那么就要通过补码反推原码了。

 

例如:

比如八位的1000_0001,对于补码来说,虽然没有符号位的概念,但是最高位依然代表了正负,如果最高位为0,则为正数,最高位为1,则为负数,这里看最高位为1,那么就是负数,且剩下的不全为0,就不能用3.1的规则算,所以这时就只能反推出原码才能更容易看懂它所表示的值,这里也分三步走:

第一步,将补码-1,得到反码

1000_0000

第二步,除了最高位全部取反,得到原码

1111_1111

第三步,通过原码来看他的值,这里发现它的值是-127

从此实现补码阅读自由。

 

//希望能帮助到你!

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值