原码、反码、补码和移码

327 阅读4分钟

原码、反码、补码和移码

机器数(机器码)

  • 一个数在计算机中的二进制表示形式叫做机器数(机器码),因此机器数是带符号的,是把正负的符号进行“数值化”后的二进制数,比如用 0 表示 + 号,用 1 表示 - 号
  • 十进制中的数 +3 转成 8 位(bit)二进制就是 00000011,而如果是 -3 的话,转成二进制就是 10000011,那么 00000011 和 10000011 这两个数就是机器数
  • 常用的机器数有原码、反码和补码等

机器数的真值

  • 因为机器数的第一位是表示符号位,所以机器数的值就不等于真正的数值,比如带符号数 10000011,真正的数值是 -3 而不是 131(10000011 直接转成十进制是 131),为了区别开来就把带符号位的机器数所对应的真正的数值称作为机器数的真值,所以 +3 和 -3 这两个数就是机器数的真值的十进制表示

true form 原码(sign-magnitude form)

  • 原码就是在真值的基础上,在真值前面添加一位符号位,非符号位为该数字绝对值的二进制表示
  • 因为原码就是一个符号位加原数字的绝对值,所以原码不能直接用于计算机进行运算,需要额外处理符号位
  • +1 的原码是 00000001,-1 的原码是 10000001
  • 原码是人类最容易理解和计算的表示方式
  • 因此 8 位二进制能够存储数值的范围就是 -1111111 到 +1111111(2^6+2^5+2^4+2^3+2^2+2^1+2^0=127),换成十进制原码的取值范围就是 -127 到 127
  • 由于计算机的逻辑电路需要设计的尽量简单,所以计算机就实现了加法运算,而加减乘数又是最基础的运算,所以其他运算都通过转换成加法和位移运算来变相完成的,比如减去一个正数就转换成加上一个负数(因此计算机里引入了反码的概念)

one's complement 反码

  • 正数的反码与原码相同,负数的反码是其原码除符号位外,其余各位取反,反码使得符号位和数值位可以一起参与运算(原理来源于数学知识推导),所以反码的取值范围也是 -127 到 127
  • 实际上反码就是这个数对于一个模的同余数,比如 3 mod 12 = 3,15 mod 12 = 3(mod 是指取模操作,这里的模 12 就是所能表示的最大值,比如相当于钟表表示 12 个小时)
  • +1 的反码是 00000001,-1 的反码是 11111110
  • 可见 +0 和 -0 的原码存在 00000000 和 10000000 这两个不一样的表示,而 +0 和 -0 的反码也存在 00000000 和 11111111 这两个不一样的表示,但事实上它们表示的都是同一个数(于是计算机里又引入了补码的概念)

two's complement 补码

  • 正数的补码与原码相同,负数的补码是其反码的基础上加 1
  • 于是 +0 和 -0 的补码就都变成 00000000 了,所以 8 位二进制原来的存储数值就空出了一个,因此就能够多表示一个最低数,就把 -0 的补码 10000000 腾给了 -128((2^7=128),不过 -128 并没有原码和反码的表示,所以补码的取值范围就是是 -128 到 127(就是 -2^7 到 2^7-1),如果是 32 位(int)二进制的取值范围就是 -2^31 到 2^31-1
  • 计算机为了人类阅读方便,会以原码的形式作展示,而在存储和计算的时候则以补码的形式

offset binary code 移码(biased representation)

  • 不管正数还是负数,将其补码的符号位取反,其余位不变,得到的就是该数的移码

总结

  • 1 正数的原码、反码、补码三者都相同
  • 2 负数的反码就是符号位不变,然后剩余位按位取反
  • 3 负数的补码就是反码加 1,所以负数的反码就是补码减 1
  • 4 移码就是不管正负数,只要将其补码的符号位取反即可