正整数的原码、反码、补码:就是该整数原本的二进制形式,其中最高位留做符号位
以 byte 字节为例,+3 的原码、反码、补码都是:
0 000 0011
负整数的
反码:除符号位取反,例如 -3 的反码如下
1 000 0011
1 111 1100
补码:负数是原码求反码再加 1,例如上面的 -3
1 000 0011 原码
1 111 1100 反码
1 111 1101 补码
当然 Java 存储和使用负整数,采用的就是补码的形式。
理解符号位
网上也有很多解释这三者的文章,但我认为他们都把问题搞复杂了。
我们不妨从最终的目的着手,看看为什么有补码、反码的出现
首先,要明白一个前提,为了简化硬件电路设计,CPU 只有加法器,没有减法器,这就要求,我们必须用另外的手段表示负数,方便加法运算。
先来理解一下,最高位符号位的含义,byte 能表示的最大的正数是
0 111 1111
换算过来是 127,如果再加 1,变成了
1 000 0000
应该对应 128,但我们说最高位是符号位对吧,我们不妨可以把符号位理解为:它的值就代表 128 ,只是个负的而已。
也可以理解为符号位是向更高位借的 128,最后要还的
计算过程
现在以 4 - 3 为例,我要把它变成 4 + (-3)
4 很好表示
0 000 0100
-3 可以表示为 -128 + 125,别忘了我们前面说符号位就是 -128,因此变成了(可以用计算机看一下 125 的二进制)
1 111 1101
下面我们做个加法,其实就是 -128 + 4 + 125,我们心算都能算,但计算机需要按二进制一位一位加,ok?
1 000 0000 这是 -128
0 000 0100 这是 4
0 111 1101 这是 125
1 000 0000 这是 -128
1 000 0001 这是 129
0 000 0001 -128 它知道,从低位进位上来的 +128,能和我恰好抵消掉
反码、补码
回过头来,再看 -3 的补码怎么来的,记得我们的目的是要凑 -128 + 125
0 000 0011 3
0 111 1100 124 反码
0 111 1101 125 补码
1 111 1101 -128+125 = -3
总结一下,不是因为有了反码,补码的定义,才出现了负数的表示,而是因为我们要统一加法、减法运算,为了能【凑出】最终的数字表示,才诞生了反码和补码,帮我们方便进行二进制推导