注意:计算机实际上是按照补码进行存储的,对计算机来说没有原码和反码这种东西,原码和反码只是为了方便我们理解而定义的一种概念。
一、原码
正数的原码就是它本身,负数的原码最高位为1。
如果用一个字节来存储整数,那么20的原码就是0001 0100,-20的原码就是1001 0100
二、反码
正数的反码跟原码一样,负数的反码按位取反,符号位不变。
如果用一个字节来存储整数,那么20的反码就是0001 0100,-20的反码就是1110 1011
三、补码
正数的补码跟原码一样,负数的补码是反码加1。
如果用一个字节来存储整数,那么20的补码就是0001 0100,-20的补码就是1110 1100
四、计算机为什么不用原码和反码,而采用补码来计算
原因是使用原码或者反码计算结果是错误的,补码才是正确的。
下面我们来看一下分别使用原码、反码和补码进行计算的结果
1、原码计算
0001 0100(20)
+ 1001 0100(-20)
-------------------------------
10101000(-40)
20和-20的和是-40,结果显然不对
2、反码计算
0001 0100(20)
+ 1111 0101(-10)
--------------------------------
0000 1001(9)
20和-10的和是9,结果显然不对
3、补码计算
0001 0100(20)
+ 1110 1100(-20)
-------------------------------
0000 0000(0)
用反码计算的结果正确
五、为什么一个字节能表示的整数范围是-128到-127
首先最高位为0,其他位为1,就代表最大的整数,就是0111 1111(127),那么最小的数应该是1000 0001(-127)
那么问题来了,一个字节如何表示-128?
我们结合上面的原码、反码和补码知识知道,我们知道1000 0000(-0)+0111 1111(+127)=1111 1111(-1)。这种情况下我们发现补码的计算也不准了,-0与127的和居然是-1。刚刚不是还说用补码计算时正确的吗?
为了解决这种特殊情况,我们认为反码1000 0000表示的是-128,不再表示-0(-0本身也没有意义,用0就可以了),然后1000 0000(-128)+0111 1111(+127)=1111 1111(-1),漂亮,所有情况下,补码的计算都是正确的了。