任何存储于计算机中的数据,其本质都是以二进制码存储。计算机的运算器只有加法运算器。所以在计算机中没办法直接做减法。
从硬件的角度来说正数+正数、负数+负数都是可以通过加法器直接相加,只有正数加负数才算是减法。原码、反码及补码的产生过程就是为了解决计算机做减法和引入符号位的问题。
1 原码
计算机保存最原始的数字,是没有正负之分,叫做“无符号数字”。
原码左边第一位存放符号,0表示正数,1表示负数。
数字 | 原码 | 负数 | 原码 |
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 |
表 四位二进制原码所能表示的所有正整数及负整数
原码表示的整数范围为(n表示二进制的位数):
优点: 原码直观易懂、与真值转换容易。
弊端: 1)0有两种表示形式。2)减法运算复杂。
计算机利用原码进行运算时,首先要判别两数符号,同号做加法,若异号则做减法。做减法运算时,还需要判定两数的绝对值大小,用绝对值大的减去绝对值小的,取绝对值大的符号为结果符号。
例如:2 - 5 ,首先用-5的绝对值减去2的绝对值:0101 - 0010 = 0011;然后取-5的符号位1,最后结果为1011。
2 反码
负数是对应正数的相反数。反码的定义为:正数的反码等于原码,负数的反码是它的原码除符号位,按位取反。
例如-5的反码表示为: -5(1101)按位取反为1010。
2.1 反码特点
1)反码的表示范围和原码一样。
2)反码不能直接用于运算。
3)反码同样存在两个0(+0与-0)。
反码通常用来由原码与补码相互转换的过度码。
3 补码
计算机中,所表示的二进制位数是有限的。在Java中byte类型是1个字节(1个字节等于8位),字节位数是8位。当执行像 [1111 1111]2 + [0000 0011]2 = [1 0000 0010]2 的二进制运算时,因为这个数据类型只能保存8为,所以最高位会被截掉,最终结果为[0000 0010]2,这种情况称为溢出。
图 时钟
在我们实际生活中,也存在这样的情况。例如,现在时钟是11点,再过2小时,时钟是指向1点。
3.1 模
模是计量器具点容量。
在时钟的例子中,时钟的模为12,当时钟指向9点时,往后拨动时针2格与往前拨动时针10格的效果是一样的。即 9 – 2 = 9 + 10。其中 9 + 10 = 19,已经溢出了12这个模,所以 9+10 = 9 + 10 – 12 = 7。
在上面这个例子中,-2 与 + 10的效果是一样的。不止是-2与10,还有像+5 与 -7,+4 与 -8…。只要是两数的绝对值相加等于12且符号相反,都满足这个情况。而我们称这两数互补。
在二进制中,假设二进制位数n为4,则其的模为2n即[1 0000]2。
3.1 补码的定义
在上个例子中,5 + (– 3) = [0101]2 - [0011]2 = [0101]2 + [ 1101]2。在计算器中是没有减法器而只有加法器。所以 5 + (– 3) 在计算机中只能表示为[0101]2 + [ 1101]2。即:
3.2 补码的特性
以下证明中,二进制的位数为n (n > 0), 而X表示原码形式下的负数。|X|表示其绝对值的原码。
1)负数的补码的补码等于该负数的原码。
2)负数的补码等于其反码+1。[1011]2 的反码 [1100]2 再加上1得到补码[1101]2。
3) 补码与其十进制的转换:X 10= -1 * 2n-1 + 除符号位外其他位累加和。
([1011]2)补 = 24-1 + 2 + 1 = -5。即其为-5的补码。
4) 补码表示范围为[10 n-10 n-2…01] 2 ~ [01n-11n-2…11]2。
[10 n-10 n-2…01] 2 表示的十进制为-2n-1,而对应的原码则无法表示。