参考教材 附注 2: 补码表示与重码问题

引入

以 8 位数据为例,0b00000000 ~ 0b11111111 对于 unsigned int 表示 0~255 一一对应。 那么如何对 signed int 进行编码呢?

可能的解决方案 1 :最高位为符号位 (True form)

对于 8 位数据,使用第 8 位作为符号位,1 表示负数、0 表示正数,其他位表示数值。

0b00000000: 0 <=?=> 0b10000000: ?

0b00000001: 1 <==> 0b10000001: -1

0b00000010: 2 <==> 0b10000010: -2

0b01111111: 127 <==> 0b11111111: -127

我们发现出现了重码问题,0b00000000 和 0b10000000 都表示 0,从表示方法来说 0b10000000 表示 -0. -0 在逻辑上是不存在的。 所以这个方案 对 数字0 的表示,出现了重码的问题。

可能的解决方案 2 :反码 (ones' complement)

对于 8 位数据,我们先确定 0b00000000 ~ 0b01111111 表示 0 ~ 127,负数则对数值部分按位取反,符号位的使用与方案 1 相同。

0b00000000: 0 <=?=> 0b11111111: ???

0b00000001: 1 <==> 0b11111110: -1

0b00000010: 2 <==> 0b11111101: -2

0b01111111: 127 <==> 0b10000000: -127

我们再次发现出现了重码问题,0b00000000 和 0b11111111 都表示 0,从表示方法来说 0b11111111 表示 -0. -0 在逻辑上是不存在的。 所以这个方案 对 数字0 的表示,也出现了重码的问题。

可能的解决方案 3 :补码 (2's complement)

对于 8 位数据,我们先确定 0b00000000 ~ 0b01111111 表示 0 ~ 127,负数则对数值部分按位取反后 + 1,符号位的使用与方案 1 相同。

0b00000000: 0 <==> 0b11111111 + 1 = 0b00000000: 0

0b00000001: 1 <==> 0b11111110 + 1 = 0b11111111: -1

0b00000010: 2 <==> 0b11111101 + 1 = 0b11111110: -2

0b01111111: 127 <==> 0b10000000 + 1 = 0b10000001: -127

正数的补码先取反后 + 1 后为其对应的负数的补码,负数的补码先取反后 + 1 后为其绝对值 (负数的补码先 -1 后取反也可以得到它的绝对值); 补码表示为有符号数的运算提供了方便,同时运算后的结果依然满足补码的表示规则。

综上所述,补码既解决了重码问题,也同时汲取了 方案 1 和 方案 2 的优点。

© 2019 kmahyyg <16604643+kmahyyg@users.noreply.github.com>. All rights reserved.

results matching ""

    No results matching ""