首先感谢南老师!
在计算机里的有符号数,最高位的1用来表示负号,所以,用 0000 0001表示正1,1000 0001表示-1,确实对人来说很直观。但其实,计算机里的数是用“补码”表示的。其中正数的补码就是原来的数(称为原码),而负数的补码是这么算的,我用倒推的来说:
补码 = 反码 + 1
反码 = 原码按位取反(1变0,0变1)
所以,-1就是1取补码,过程如下:
先取反 0000 0001 ---> 1111 1110
然后加1得补码: 1111 1110 + 1 = 1111 1111
(当然这里为了方便,就取了8位,其实整数现在都是32位了,结果是32个1)。
现在,你知道如何计算-2了吗? 为什么要搞反码,补码这么个转换呢? 这个原因要说长就很长的,但简单地讲,这又是一个在人的直观和机器的高效之间取一个平衡:
我们先来看一个10进制的数运算:
1 + (-1) = 0 //10进制中,1加负1应为0.
然后,假如用1000 0001来表示-1的话。按照计算机计算加法的规则,它是每位加的,结果是:
0000 0001 + 1000 0001 = 1000 0010 //-2
结果变成-2了,其中后面两个0001 相加变成2,而前面的用于表示负号的1,被“继承”下来了……显然,原来计算机最直观的(对人来说也很直观的)算法,不灵了!怎么办?痛苦
但更痛苦的事还在0这个数上。按10进制,0和-0可是完全相等的。但如果用二进制,0000 0000 和 1000 0000 参加起运算,可是完全不同。或许可以通过电路设计,来强制让计算机去实现一个规则: 碰到1000 0000就先转换为0000 0000。但可要知道加减法计算是计算机计算一切的基础,如果从这最底层就必须有一个转换会极大影响性能!何况前面那个问题也必须有个强制规则!规则最好越简单越好,那就是规定前面的补码转换规则,这个转换过程对于计算机来说很迅速的逻辑电路转换。
你看,第一个问题 1 + (-1)
0000 0001 + 1111 1111 = 0000 0000
看明白这个计算过程吗?其实就是最低位的两个1相加后,造成每一位都进位,最高位直接溢出(丢了)。如果你还算不清,就算算这个10进制的:
1 + 999 = 1000 (最高位1丢失,就成0了)
然后是第二个问题,0的表示。如果您把0当成正数,那么它是这样表示的:
0000 0000
如果你当它是负数,那么
取反 1111 1111 ,再加1,以求补 ,哈哈又成 0000 0000这回在逻辑上没有错误了!明白了吧?当补我在学习这一段知识时,只能说:高,实在高! 想出补码的前辈,真是高人啊。