kikimo

原码、反码与补码

二进制数的表示形式有三种:原码、补码和反码。 任意形式的二进制数, 最高位(MSB)都表示符号位,0 表示正数,1 标致负数。 例如原码总:00000001b表示正一,10000001b表示负一。 任意形式的二进制数的正数表示法都一样,他们差别在于对负数的表示上,以-1为例:

  1. -1的原码的表示为10000001b
  2. -1的反码表示为11111110b,它是在原码的基础上,符号位不变,其余位取反
  3. -1的补码表示为11111111b,它的计算方法是将-1的反码加一

反码的主要作用就是用来快速计算补码,而补码的意义在于统一正数的加减法操作:a - b可以直接用a + (b的补码)表示。

补码运算的原理

这个推导是错的

为什么补码能够用加法运算来替代减法运算? 这主要是使用了同余的原理。 首先,对于某个负数,我们可以找出它的正数同余,例如:

-3=125 mod 128

根据同余的运算规则,有:

(5-3)=(5+125) mod 128
(5-3) mod 128 = 2
(5 + 125) mod 128 = 2

模为什么取 128? 128 是为了方便的计算负数的同余,同时,它还和变量的字长有关。 我们看模为 128 时,可以如何计算负数的余数,首先:

-3 mod 128 = 128 - 3

所以问题可转化为如何快速计算 128 - 3,又:

3 + (-3[反码]) + 1 = 128
128 - 3 = -3[反码] + 1

-3[反码] + 1就是前面提到的负数补码的计算方法, 模取128可以方便我们快速的计算负数的补码。 模取128另外一个原因和变量的字长有关,如果变量是8位, 那么它的某就应该是128,如果是16为,那就应该是32768,也就是变量的 MSB