简介
学习补码阶段一直没有搞清楚八位的补码为啥能多出个-128
,因为对补码的理解不到位,影响到浮点数范围的计算,终于忍无可忍下决心彻底搞懂。
首先需知
八位二进制可表示的范围为:
原码:-127~127
反码:-127~127
补码:-128~127
原因
原码
第一位是符号位(负数为1,正数为0)。
也就是 1
111 1111b 中首位1
表示这个数是负数。
剩余的 _
111 1111b 转换为十进制是:64+32+16 +8+4+2+1 = 127
所以源码的1111 1111b 表示的是十进制-127
同理源码的0111 1111b 表示的是十进制+127
注意!源码下的0有两种表达方式:
1
000 0000b 对应的 -0 和 0
000 0000 对应的+0
反码
正数的反码是本身,负数的反码是除符号位后剩余的低位取反。
重点来了,一定要认清爸爸: 反码从原码计算来的!!!
原码的 0111 1111 对应 十进制的127 反码表示为 0 111 1111
原码的 1111 1111 对应 十进制的-127 反码表示为1 000 0000
原码的 0000 0000 对应十进制的 +0 反码表示为0 000 0000
原码的 1000 0000 对应十进制的 - 0 反码表示为1 111 1111
反码的零也是有两个,一个正零,一个负零。
补码
正数的补码是原码,负数的补码是其反码+1
一定要!一定要!认清爸爸: 补码是从原码计算来的!!!
原码的 0111 1111
对应 十进制的127 反码表示为 0 111 1111
补码表示为 0 111 1111
原码的 1111 1111
对应 十进制的-127 反码表示为1 000 0000
补码表示为 1 000 0001
原码的 0000 0000
对应十进制的 +0 反码表示为0 000 0000
补码表示为 0 000 0000
原码的 1000 0000
对应十进制的 - 0 反码表示为1 111 1111
补码表示为 0 000 0000
注意到问题所在了么? 正负0 的补码都是 0 000 0000
!!!
计算资源何其宝贵,怎么能浪费?
剩下的一个补码1 000 0000b
如何利用?
如果用9位二进制数表示,则原码的 1
1000 0000 对应十进制的 -128
(原码只能9位才能表示出-128,最高位为符号位),反码表示为 1
0111 1111 补码表示为 1
1000 0000
-128补码的符号位是符号位 是符号位溢出了 。
如果用9位二进制数表示,则原码的 0
1000 0000对应十进制的+128
,反码表示为0
1000 0000,补码表示为0
1000 0000,略去高位符号位,咦!?你会发现这个数也可以表示二进制的补码1 000 0000b
。那么问题来了,为啥八位有符号二进制数下 1 000 0000b
表示的是-128而不是+128呢 ?
这里需要了解模运算,正的八位二进制数所能表示的最大值是127,我们再加一个正数,正数加正数肯定是正数,若符号位变成1则一定是产生溢出了
。127 + 1 = 0 111 1111b + 0 000 0001 = 1 000 0000b = ???。电路中发现产生溢出,则会发生取模运算,既“由阳转阴”
,也就是1 000 0000b为啥对应的是负的
!
加强理解
正的八位二进制数所能表示的最大值是127,我们再加 2,正数加正数肯定是正数,127 + 2 = 0 111 1111b + 0 000 0010 = 1 000 0001b = ???。电路中发现产生溢出,则会发生取模运算,同样也是“由阳转阴”
,结果为十进制的 多少呢? 注意补码运算完还是补码
,补码转原码是 : 先补码减1 然后除符号位其他位取反,也就是原码的 1 111 1111b,对应十进制 -127
!!!
… …
… …
… …
正的八位二进制数所能表示的最大值是127,我们再加 127,正数加正数肯定是正数,127 + 127 = 0 111 1111b + 0 111 1111 = 1 111 1110b = ???。电路中发现产生溢出,则会发生取模运算,同样也是“由阳转阴”
, 注意补码运算完还是补码
,补码转原码是 : 先补码减1 然后除符号位其他位取反,也就是原码的 1 000 0010b,对应十进制 -2
!!!
简记