补码的再认识
温故知新。
最早接触补码是在好几年前的大学课堂里。正负数原码、反码、补码之类的知识学起来也没什么难度,相互之间换算的公式很简单,凭着当时年轻,记忆力、理解
力都在顶峰,在没有搞清楚原理本质的情况下也稳稳的过了考试。
直到最近偶然之间又接触到了补码,发现按照负数补码的计算公式,自己完全算不出来为什么-128的补码是 1000 0000,一计算就得到9位的结果(1 1000 0000)。百度了以后没看到能够完全说服我自己的答案。于是好吧,自己研究。
不愿意理解的小伙伴们只要记住两点:
- -128的补码就是 1000 0000
- 负数的补码 = 256 - 负数的绝对值
补码的本质
为什么要用补码,百度里面有很多答案,比如现在机器码存储计算的都是用补码,没有减法运算器,原码反码算不准之类的巴拉巴拉。百度百科说的比我好很多,这里就不记录了。
我对于补码的理解可以概括为两句话,下面所有的文字,都是以下两句话的体现:
- 补码计算的本质时是映射。
- 补码计算的意义:用加法代替减法。
我们知道8位2进制数补码的范围是【-128,127】,并且用最高位区分了该二进制数的正负。
即:
- 正数:0000 0000 - 0111 1111 ( 0 - 127 )
- 负数:1000 0000 - 1111 1111 (128 - 255)
也就是说将0-255,这256个正数的前128个映射成了正数,后128个映射成了负数。
0 | 1 | 2 | … | 126 | 127 | 128 | 129 | 130 | … | 254 | 255 |
---|---|---|---|---|---|---|---|---|---|---|---|
0000 0000 | 0000 0001 | 0000 0010 | … | 0111 1110 | 0111 1111 | 1000 0000 | 1000 0001 | 1000 0010 | 1111 1110 | 1111 1111 | |
0 | 1 | 2 | 126 | 127 | ??? | -127 | -126 | -2 | -1 |
你会发现,其实存在这么一个对应关系
{
0:0,
1:1,
2:2:
...
126:126,
127:127,
128:-128,
129:-127,
130:-126,
...
254:-2,
255:-1
}
并且呢,补码的加法计算,本质就是帮助我们找到上述映射关系。
举几个例子:
#正数相加 :1+126
0000 0001 + 0111 1110 =0111 1111 #根据以上映射,结果为127。
#正负数相加 -2+5
0000 0101 + 1111 1110 =259 #找不到映射?别急,对256取余。 259%256=3
#负数相加 -127+(-1)
1000 0001 + 1111 1111 = 129 + 255 =384 #对256取余,结果为:384%256=128
至此,我们可以得到 1000 0001 + 1111 1111 = 1000 0000 ,所以 -128对应的二进制原码为1000 0000
所以说,想出用补码相加的方式来替减法的人一定数学很好,哈哈。
最后稍微复习一下原码、反码、补码的基本知识
类型 | 正数(例:5) | 负数 (例:-5) |
---|---|---|
原码 | 正数的原码是本身 0000 0110 | 负数的原码是本身 1000 0110 |
反码 | 正数的反码是本身 0000 0110 | 负数的反码是除最高位外,其余求反 1111 1001 |
补码 | 正数的部码是本身 0000 0110 | 负数的原码是反码+1。 1111 1010 |
8位2进制的补码范围:[-128,127]