计算机中负数的表示方式,经常被提起的有三种:原码、移码、反码、补码
原码
原码,就是把二进制的最高位作为符号位(0:正号;1:负号),剩下的部分表示该数的绝对值。
我们以8位二进制举例:
如果扩展为16位二进制呢,就是下面这样:
从上面我们可以看到,原码负数从8位扩展到16位呢,需要再符号位的右边插入0,这个操作,硬件实现的时候,比较复杂。
再看一下原码的加法:
两个正数相加:直接加就行了
两个负数相加:绝对值相加,符号位不变
正数加负数:和的符号与绝对值较大的相同,和的绝对值等于较大的绝对值减去较小的绝对值。
可以看出来,原码整数的加法法则还是很复杂的。
反码
反码的正数,跟原码一样;负数,是把绝对值取反。
我们还以8位二进制举例:
如果扩展为16位二进制呢,就是下面这样:
从上面呢我们可以看到,反码从8位扩展到16位,只要看最高位就可以了,最高位是1,就再左边补8个1,如果最高位是0,就再左边补8个0,这个逻辑比原码简单多了。
我们研究一下取反的操作,前面我们学过,可以通过异或的方式,来给二进制取反,比如8位二进制取反:
^ ==
我们也可以认为是:
再看一下反码的加法:
两个正数相加:直接加就行了
两个负数相加:两个数取反后相加,加完再取反。
正数加负数:负数取反后,与正数比较,若负数绝对值大,则负数绝对值减去正数后取反;若正数绝对值大,则正数减去负数绝对值,即为和。
我们可以看出来,反码整数的加法法则,也很复杂。
补码
补码的正数,跟原码一样;补码的负数,是把绝对值取反后再加1(即反码再加1)。
我们还以8位二进制举例:
如果扩展为16位二进制呢,就是下面这样:
前面我们说了,-1 取反操作相当于:
-1 取反再加1呢,就相当于:
大家发现没,补码这么一操作,就是《离散数学》中讲的“模256同余”,同余数有一个特点就是,加一个负数,相当于加上与它同余的正数,即把减法转化成了加法,或者说的抽象一点,你可以认为是十进制数255,也可以认为是十进制数 -1,因为:
由模运算的运算法则,补码的加法运算规则非常统一,不需要考虑符号位,两个数直接加就可以了。
也许你对上述结论不是很理解,也暂时不需要深究,随着学习的深入,特别是学习了《离散数学》后,你会逐渐对补码有更深刻的理解。
其实我们这样理解补码,它把 ~ 分成了两段: ~ 和 ~。
~就用来表示正数
~ ,如果用来表示负数,再综合模256同余数:、、……。是非常不错的选择。
移码
移码,就是把二进制的值,减去一个约定值之后的差,作为该二进制表示的数值。
我们还以8位二进制举例,比如我们约定的值是127,那么表示的值就是:
并且
所以当用二进制用移码表示数时:
移码的加减法,可能学过,但是都忘了,这里就不说了,感兴趣的同学,可以自己去查资料。