原码
如果我们在内存中分配4位(bit)来存放无符号的数字,它就是下面这样子的:
十进制 | 二进制(4位) |
---|---|
0 | 0000 |
1 | 0001 |
2 | 0010 |
3 | 0011 |
4 | 0100 |
5 | 0101 |
6 | 0110 |
7 | 0111 |
数字是一个抽象的概念,生活中为了表示欠别人钱这个概念,就产生了正数和负数。
为了表示正数和负数,就发明了『原码』。把左边第一位用来存放符号位,0表示正数,1表示负数:
十进制 | 原码(正数4位) | 十进制 | 原码(负数4位) |
---|---|---|---|
0 | 0000 | -0 | 1000 |
1 | 0001 | -1 | 1001 |
2 | 0010 | -2 | 1010 |
3 | 0011 | -3 | 1011 |
4 | 0100 | -4 | 1100 |
5 | 0101 | -5 | 1101 |
6 | 0110 | -6 | 1110 |
7 | 0111 | -7 | 1111 |
原码的存储方式方便人类查看,但是却苦了计算机。
我们知道(+1)和(-1)相加是0,但是计算机若用原码相加就会算出:0001 + 1001 = 1010,十进制就是-2。这不是我们想要的结果。而且还有另外一个问题,这里有一个(+0)和(-0)。
反码
为了解决正负相加等于0的问题,在原码的基础上,又发明了『反码』。
反码是用来处理负数问题的,它的符号位置和原码一样不变,但是其它位置相反:
十进制 | 反码(正数4位) | 十进制 | 反码(负数4位) |
---|---|---|---|
0 | 0000 | -0 | 1111 |
1 | 0001 | -1 | 1110 |
2 | 0010 | -2 | 1101 |
3 | 0011 | -3 | 1100 |
4 | 0100 | -4 | 1011 |
5 | 0101 | -5 | 1010 |
6 | 0110 | -6 | 1001 |
7 | 0111 | -7 | 1000 |
使用反码代替原码,则解决了正负数相加等于0的问题。
(+1) + (-1) =0001 + 1110 = 1111,在反码中1111表示-0。
但是上面还提到一个问题:同时有两个零存在,+0和-0。
补码
精益求精的人类希望只有一个零存在,于是有发明了『补码』。补码同时解决了正负数相加等于0,和解决同时存在两个零的问题。
补码是在反码的基础上,补充了一个新的代码:将负数的反码+1。
十进制 | 补码(正数4位) | 十进制 | 补码(负数4位) |
---|---|---|---|
0 | 0000 | -0 | 0000 |
1 | 0001 | -1 | 1111 |
2 | 0010 | -2 | 1110 |
3 | 0011 | -3 | 1101 |
4 | 0100 | -4 | 1100 |
5 | 0101 | -5 | 1011 |
6 | 0110 | -6 | 1010 |
7 | 0111 | -7 | 1001 |
反码中的(-0)即1111再加上1后,就变成了10000。有得就有失,此时丢掉最高位就得到了0000,刚好得到了0。
这样就解决了正负数相加等于0的问题,同时也解决了(+0)和(-0)同时存在的问题。
对于在计算机中正负数的存储与计算方式,不断改进后,最终选择了『补码』的方案。
总结:原码是为了方便人类查看,反码过渡的中间产物。计算机实际使用中用来运算和存储的都是补码。