提起补码,就不得不提另外两个难缠的家伙:原码、反码。
计算机中,表示有符号的整数一共就用到这3种码,它们之间是有一定依存关系的。
一、补码的地位
它们的共同点是都有符号位和数值位,最高位为符号位,其他位为数值位。符号位用0表示“正”,1表示“负”。区别仅在于数值位不同。
单从名字就可以看出来,原码,就像原始人一样,是最初的还没开始进化的物种,只适用于考古。
反码,一身反骨,听起来就像反人类一样,不堪大用。
只有补码,像windows补丁,修修补补后,才好使用。
二、补码的规则
既然只用补码,为什么要整出这么多码呢?因为水是有源滴,树是有根滴,叫补码是有原因滴。
详细原因参见《负数在计算机内的编码》一文
可以说,原码、反码就是补码的爹妈。
它们之间的繁衍链条是这样的:
①遗传性:正数和0体现三码的遗传特征,其原码、补码、反码都是它本身。
②变异性:正数的符号位由0改为1就变成负数的原码。负数的反码为其原码取反(除符号位),补码为反码加一。
例如,9的原码、反码、补码都是0000 1001。(这里用最简单的8位2进制来表示);-9的原码为1000 1001(符号位由0变1)、反码为1111 0110、补码为1111 0111。
三、补码的优点
使用补码就是吃十全大补丸,好处多多。
(1)不用区分符号位和数值位。
在计算时,可以将符号位和数值域统一处理,不做区分,这样便可大大简化电路系统。
(2)一种算法搞定两种计算。
使用补码,可用加法实现减法。比如前面说的9的补码是0000 1001,-9的补码是1111 0111,9-9 = 0000 1001 + 1111 0111=0。
这样,计算机只需要一个叫做“加法器”的部件,就能完成加减法的计算。
这是因补码有一个非常重要的性质:对于一个数A,它的补码就是能够使得A和它的补码相加得到0的那个数。换句话说,如果一个数A的补码是B,那么A + B = 0。
四、补码公式
1.补码转原码
正数和0没什么可说的,三码都是一样,还转个毛线!这里只讨论负数的转码。
将一个负数的补码转为原码,其实就是对该补码再求补码:
比如补码为1111 1001:
①求反码:符号位“1”不变,其它位求反,故反码为:1000 0110
②求补码:反码加1,即1000 0110 + 1 = 10000111,这就是-7的原码。
2.求负数的补码
求一个十进制负数X的补码有一个公式:X补码 = 2^N + X(X<0)。
公式中的N表示位宽,即N位二进制数。
因为现在的int型基本都是用4个字节(32位二进制数)表示的,X的补码是2^32+X,所以-1的补码为2^32-1=4294967295。如果是8位二进制数,其补码就是2^8+X。
3.求负数的补码的绝对值
要求一个负二进制数的补码的绝对值,其实就是求它的相反数,只要对补码全部取反并加1,就可得到其绝对值。
比如-65的补码是1011 1111,各位取反:0100 0000,加1得:01000001(+65)