简单来说
1、解决0和-0的问题
2、统一加法和减法运算
下面我们详细解释上面两点
前言
对于计算机硬件,实现减法器更为复杂。利用加法器可以简化硬件电路设计
1、为什么加法器能解决减法问题?它利用了什么原理?
为了深入理解补码的优越性,我们从生活中的钟表入手。
表盘上时针指向10点钟,而正确的时间是5点钟,要把时针拨回到5点钟有两种方法:第一种方法是将时针往回拨5个小时指向5点钟,第二种方法是将时针往前拨7个小时指向5点钟。用数学式表示出来,第一种方法为10 - 5 = 5;第二种方法为10 + 7 = 12 + 5 = 5 ,由于表盘上最大的数是12,当时间超过12点以后,12自动丢失,只保留减去12以后的余数5。
从效果上来看,与是等价的,都使时针指向了5点,12称为模。7是-5对模12的补数,也称为补码。该实例说明了对模12而言,减法运算可以通过加法运算来实现。
2、接下来,用二进制证明钟表原理,以10 - 5 = 5为例
首先,计算出-5的补数
根据钟表原理,补数可以用最大值相减求出,如12 - 5 = 7;对于二进制,以int8位为例,最大值127,则-5的补码是122;
但是二进制和钟表有一个不同的地方是:二进制补码需要带上符号位;如果不带符号位,就会变成两个正数相加,并且,还会失去负数的意义。所以正确的补码应该是-122,int8位表示1111 1010
然后,两数相加
0000 1010 [10]原
+ 1111 1010 [-5]补
1 0000 0100
最高位1舍弃,得到0000 0100,结果为4。但预期结果是5,为什么会算错?是哪一步计算错呢?
这样,我们一个一个1的相加,[-5]补 + 10相当于1111 1010加十次一
第一次:
1111 1010
+ 0000 0001
1111 1011
第二次:
1111 1011
+ 0000 0001
1111 1100
第三次:
1111 1100
+ 0000 0001
1111 1101
第四次:
1111 1101
+ 0000 0001
1111 1110
第五次:
1111 1110
+ 0000 0001
1111 1111
第六次:
1111 1111
+ 0000 0001
1 0000 0000 (最高位舍弃,即0)
剩下四次,我们直接+4:
0000 0000
+ 0000 0100
0000 0100
计算结果确实为4,为什么计算不出5呢?
问题出在第六次运算的时候,运算结果变为0这一步。如果是钟表原理,它是没有0刻度的,它的最小值是1;但是二进制相比钟表,多出了0刻度值;这是二进制与钟表不一样的地方
所以对于二进制,模应该是128,而不是127;所以5的补数应该是128 - 5 = 123 (符号位保留,int8位表示1 111 1011)
我们再算一遍
0000 1010 [10]原
+ 1111 1011 [-5]补
1 0000 0101 (最高位舍弃,即5)
这次终于算对了。
简单来说,最大值127(即111 1111)减去5,得到122(即5的反码);又因为二进制多了0刻度,所以还要再加1,得到123;符号位保留,刚好就是-5的补码。
3、为什么可以解决-0问题?
原因很简单,因为-0被-128所占用
我还是给大家说明一下吧
①为什么-0表示的是-128
②为什么int8位取值范围是[-128,127],不是[-127, 127]
两个其实是同一个问题,我就一起来解释
正数的取值范围[0, 127],这个没什么好说的。对于负数,原码表示范围确实是[-0,-127]。但是从编码的角度看,这个-0是不应该存在的;补码就相当于计算机中的一种编码方式,它确保每一个编码对应一个数。负数的取值范围,是从补码反过来得出。补码同样有128个编码,但是对应的数值范围是[-1,-128],而不是[-0,-127]
我来解释一下-128是怎么得来的?
-127 - 1 = -128 可以很好的解释这一点
[-127]原 = 1111 1111 [-127]补 = 1000 0001
[-1]原 = 1000 0001 [-1]补 = 1111 1111
1000 0001 [-127]补
+ 1111 1111 [-1]补
1 1000 0000
溢出位1舍弃,得到补码1000 0000,这个补码就是对应着-128
需要注意:补码1000 0000无法还原得到-128;同理,-128也无法求补得到1000 0000;-128和补码1000 0000就是一种对应关系。