大家都知道负数的补码是其绝对值的原码取反加一,以八位有符号数为例:
5原码: 0 000 0101
-5补码: 1 111 1011
但是为什么是这样呢?
补码之所以存在,是因为计算机不能(或者不方便,待研究)像我们人类那样去做减法,所以通过特定的方式让计算机通过做加法的方式实现减法的效果。这种方式的原理,拿钟表来说明一般会比较容易理解。
比如现在是下午5点,然后我们想知道之前2个小时几点,但钟表又不能倒退,怎么办呢?我们知道,对钟表而言,12个小时是一个循环,12个小时前也是5点,但是是上午五点。
上午5点 + 12小时 = 下午5点
那么2小时前的时间可以这么算:
下午5点 - 2小时 = 上午5点 + 12小时 - 2小时 = 上午5点 + 10小时
= 下午五点 + 回拨一圈 + 往后走回拨多了的(12 - 2)小时
其实补码的原理类似,还以8位有符号数字为例,想象一个钟表有0~127共128个刻度,它的循环为128:
"下午5" - 2 = "上午5" + 128 - 2 = "上午5" + 126 = "下午5" - 128 + 126 =
"下午5" +(-128 + 126)= "下午5" +(-128) + (128 - 2)
从以上可以看出,减去x时可以这样算,先回拨一圈(-128),然后再往后走回拨多了的(128 - x)步。
在补码中可以将最高位符号位理解为回拨一圈的标记,比如
0 000 0101 //最高位符号位为0,表示“下午5”
1 000 0101 //最高位符号位为1,表示“下午5”回拨了一圈,也就是“上午5”
然后再看下如何从x迅速求出(128 - x),以2和126为例,当两个数和为127时,是相互取反的关系。
2+125 = 127
0 000 0010
0 111 1101
----------------
0 111 1111
可知,当两个数和为128,是相互取反加1的关系。
-128 : 1 000 0000
126: 0 111 1101
2: 0 000 0010
(-128) + 126:1 111 1101
最终可知,对2取反加1,分为两个部分:
1)低7位:表示求出回拨多了的部分,也就是(128 - 2) = 126
2)最高位符号位:对符号位取反,符号位变为1,代表着对某个数"回拨一圈",即-128;