1 二进制表示法
概念:将一个数值用二进制表示,置于最低位,按指令长度将高位补零。
如 5
在二进制中表示为 101B
(B为二进制单位)在32位计算机中表示为:
00000000 00000000 00000000 00000101(5 二进制)
但由于计算机中没有正负只有 0
和 1
,二进制是没办法直接表示负数,为了解决这个问题原码就诞生了。
2 原码
2.1 原码表示法
在数值前面增加了一位符号位(即最高位),正数该位为 0
,负数该位为 1
,其余位表示具体数值。
也就是说原码中的正数与二进制表示一致,负数最高位设为 1
。
00000000 00000000 00000000 00000101(5 原码)
10000000 00000000 00000000 00000101(-5 原码)
2.2 原码表示法的问题1:±0
原码表示法的 0
有两种表示方法,这是不合理的:
00000000 00000000 00000000 00000000(+0 原码)
10000000 00000000 00000000 00000000(-0 原码)
2.3 原码表示法的问题2:无法做减运算
计算机中并没有减运算,要想做减运算只能加负数,例如:5 - 5
→ 5 + (-5)
。
而在原码表示法中其运算结果表示为:
00000000 00000000 00000000 00000101(5 原码)
+ 10000000 00000000 00000000 00000101(-5 原码)
= 10000000 00000000 00000000 00001010(-10 原码)
这显然是错误的。
3 反码
3.1 反码表示法
正数同原码及二进制一致;负数除原码的符号位 1
不变,其余位均取反(如果是 0
就变成 1
,如果是 1
就变成 0
)。
00000000 00000000 00000000 00000101(5 反码 = 原码 = 二进制)
11111111 11111111 11111111 11111010(-5 反码)
3.2 反码表示法的原理
这里实际上是运用了模的概念,例如时钟里的模是 12
,时钟只有 0
~ 11
,到 12
就溢出重新变为 0
。
此时,对于 0
~ 11
任意一个数 A
:有 A - 4
= A + 8 - 12
。
则 4
和 8
互为补数,即相加之和正好等于模 12
。
根据这一性质,类比32位计算机,计量范围是 0 ~ 232-1,则模是 232,即:
10000000 00000000 00000000 00000000(模 二进制)
这样可以将减法运算转化:- B
= + B的补数 - 模
= + (模 - B) - 模
。
10000000 00000000 00000000 00000000(模 二进制)
- 0000000 00000000 00000000 00000101(5 二进制)
= 1111111 11111111 11111111 11111011(模-5,即5的补数 二进制)
- 10000000 00000000 00000000 00000000(模 二进制)
= 11111111 11111111 11111111 11111011(结果)
11111111 11111111 11111111 11111010(-5 反码)
由此可见,5
的补数的二进制减去模后,正好等于 -5
的反码 + 1
。
二进制数的数值
B
取值范围是 0 ~ 232-1,不会超过模,因此模 - B
一定为31
位的正数。再减去模 232,也只是将符号位设为1
整体变为同绝对值负数,不会影响前31
数值。
相当于十进制中100 - n > 0, n ∈ [0, 99]
,n - 100 = -n
。
所以,反码无法直接进行减法运算:
- 结果为正数时比正解少
1
:00000000 00000000 00000000 00000101(5 反码 = 原码 = 二进制) + 11111111 11111111 11111111 11111110(-1 反码) = 00000000 00000000 00000000 00000011(3 反码,高位溢出忽略) → 00000000 00000000 00000000 00000000(3 原码)
- 结果为负数时没有问题:
这里会没问题不是因为反码是对的,而是因为反码中仍存在00000000 00000000 00000000 00000101(5 反码 = 原码 = 二进制) + 11111111 11111111 11111111 11111000(-7 反码) = 11111111 11111111 11111111 11111101(-2 反码) → 10000000 00000000 00000000 00000010(-2 原码)
±0
的问题。
3.3 反码表示法的问题:±0
反码表示法的 0
有两种表示方法,这是不合理的:
00000000 00000000 00000000 00000000(+0 反码)
11111111 11111111 11111111 11111111(-0 反码)
由上例:
- 将
5 - 7
看作5 - 5 - 2
:
此时,结果依然比正解少00000000 00000000 00000000 00000101(5 反码 = 原码 = 二进制) + 11111111 11111111 11111111 11111010(-5 反码) = 11111111 11111111 11111111 11111111(-0 反码) + 11111111 11111111 11111111 11111101(-2 反码) = 11111111 11111111 11111111 11111100(-0 反码) → 10000000 00000000 00000000 00000011(-3 原码)
1
。 - 将
5 - 7
看作(5 - 5) - 2
:
此时,将00000000 00000000 00000000 00000101(5 反码 = 原码 = 二进制) + 11111111 11111111 11111111 11111010(-5 反码) = 11111111 11111111 11111111 11111111(-0 反码) + 00000000 00000000 00000000 00000001(1 反码 = 原码 = 二进制) = 00000000 00000000 00000000 00000000(+0 反码) + 11111111 11111111 11111111 11111101(-2 反码) → 10000000 00000000 00000000 00000010(-2 原码)
-0