原码、反码、补码
接下来我们主要介绍十进制数用二进制表示的不同方法,所以为了简洁,我们用一个字节,也就是 8 个 bit 来表示二进制数。
原码
| 十进制 | 原码 |
|---|---|
| 2 | 0000 0010 |
| -2 | 1000 0010 |
原码其实是最容易理解的,只不过需要利用二进制中的第一位来表示符号位,0 表示正数,1 表示负数,所以可以看到,一个数字用二进制原码表示的话,取值范围是 - 111 1111 ~ +111 1111,换成十进制就是 - 127 ~ 127。
反码
在数学中我们有加减乘除,而对于计算机来说最好只有加法,这样计算机会更加简单高效,我们知道在数学中 5-3=2,其实可以转换成 5+(-3)=2,这就表示减法可以用加法表示,而乘法是加法的累积,除法是减法的累积,所以在计算机中只要有加法就够了。
一个数字用原码表示是容易理解的,但是需要单独的一个 bit 来表示符号位。并且在进行加法时,计算机需要先识别某个二进制原码是正数还是负数,识别出来之后再进行相应的运算。这样效率不高,能不能让计算机在进行运算时不用去管符号位,也就是说让符号位也参与运算,这就要用到反码。
| 十进制 | 原码 | 反码 |
|---|---|---|
| 2 | 0000 0010 | 0000 0010 |
| -2 | 1000 0010 | 1111 1101 |
正数的反码和原码一样,负数的反码就是在原码的基础上符号位保持不变,其他位取反。 那么我们来看一下,用反码直接运算会是什么情况,我们以 5-3 举例。 5 - 3 等于 5 + (-3)
| 十进制 | 原码 | 反码 |
|---|---|---|
| 5 | 0000 0101 | 0000 0101 |
| -3 | 1000 0011 | 1111 1100 |
5-3
= 5+(-3)
= 0000 0101(反码) + 1111 1100(反码)
= 0000 0001(反码)
= 0000 0001(原码)
= 1
这不对呀?!! 5-3=1?,为什么差了 1? 我们来看一个特殊的运算:
1-1
= 1+(-1)
= 0000 0001(反码) + 1111 1110(反码)
= 1111 1111(反码)
= 1000 0000(原码)
= -0
我们再来看一个特殊的运算:
0+0
= 0000 0000(反码) + 0000 0000(反码)
= 0000 0000(反码)
= 0000 0000(原码)
= 0
我们可以看到 1000 0000 表示 - 0,0000 0000 表示 0,虽然 - 0 和 0 是一样的,但是在用原码和反码表示时是不同的,我们可以理解为在用一个字节表示数字取值范围时,这些数字中多了一个 - 0,所以导致我们在用反码直接运算时符号位可以直接参加运算,但是结果会不对。
补码
为了解决反码的问题就出现了补码(补码也是计算机存储的格式)。
| 十进制 | 原码 | 反码 | 补码 |
|---|---|---|---|
| 2 | 0000 0010 | 0000 0010 | 0000 0010 |
| -2 | 1000 0010 | 1111 1101 | 1111 1110 |
正数的补码和原码、反码一样,负数的补码就是反码 + 1。
| 十进制 | 原码 | 反码 | 补码 |
|---|---|---|---|
| 5 | 0000 0101 | 0000 0101 | 0000 0101 |
| -3 | 1000 0011 | 1111 1100 | 1111 1101 |
5-3
= 5+(-3)
= 0000 0101(补码) + 1111 1101(补码)
= 0000 0010(补码)
= 0000 0010(原码)
= 2
5-3=2!!正确。 再来看特殊的:
1-1
= 1+(-1)
= 0000 0001(补码) + 1111 1111(补码)
= 0000 0000(补码)
= 0000 0000(原码)
= 0
1-1=0!!正确 再来看一个特殊的运算:
0+0
= 0000 0000(补码) + 0000 0000(补码)
= 0000 0000(补码)
= 0000 0000(原码)
= 0
0+0=0!!也正确。 所以,我们可以看到补码解决了反码的问题。 所以对于数字,我们可以使用补码的形式来进行二进制表示。
5的负数是-5 也可以~5+1(取反加一来表示-5)
