一、概念清单

  1. 机器数

  2. 真值

  3. 原码

  4. 反码

  5. 补码

二、概念详解

1. 机器数

  1. 机器数是一个数在计算机中的二进制表示形式。

  2. 机器数带符号,最高位存放,正数为0,负数为1。

    十进制数+3,计算机字长为8位的话,转换二进制为00000011
    十进制数-3,计算机字长为8位的话,转换二进制为10000011
    上述这两个二进制就是机器数。

2. 真值

  1. 由于符号位的存在,机器数不等于真值。

  2. 带符号的机器数,真正的数值。

    -3是真值,它的机器数是10000011(其形式值为131(十进制))

3. 原码

  1. 原码是符号位加上真值的绝对值,即第一位为符号位,其余位表示值。

        十进制数+1原码为 00000001
        十进制数-1原码为 10000001
    
  2. 因为第一位是符号位,所以8位二进制的取值范围为:

    [11111111,01111111]

    
        [-127,127]
        
  3. 原码是人脑最容易理解和计算的编码方式。

  4. 无符号数用原码。

4. 反码

  1. 正数的反码是其本身。

  2. 负数的反码是其原码基础上,符号位不变,其余各位取反。

        [+1] = [00000001]【原】 = [00000001]【反】
        [-1] = [10000001]【原】 = [11111110]【反】
  3. 反码不容易被人脑直接看出真值,通常需要转换成原码

5. 补码

  1. 正数的补码是其本身。

  2. 负数的补码是其原码的基础上,符号位不变,其余各位取反,最后+1。

        [+1] = [00000001]【原】 = [00000001]【反】 = [00000001]【补】
        [-1] = [10000001]【原】 = [11111110]【反】 = [11111111]【补】
  3. 补码不容易被人脑直接看出真值,通常需要转换成原码

  4. 计算机中,有符号数采用补码

三、有符号数采用补码的意义与方法

  1. 意义:为了让符号位参与运算,以简化基础电路设计。

  2. 方法:

    举例来说:限定为8位二进制,计算十进制的表达式:1-1=0

    • 若机器码采用原码来计算,会是这样的结果:

      
          1-1 = 1 + (-1)= [0000 0001]【原】+[1000 0001]【原】= [1000 0010]【原】= -2【十进制】
      //明显错误
      
    • 若机器码采用反码来计算,会是这样的结果:

          1-1 = 1 + (-1)= [0000 0001]【原】+[1000 0001]【原】= [0000 0001]【反】+[1111 1110]【反】= [1111 1111]【反】= [1000 0000]【原】= -0 【十进制】
          //明显错误,0应该是唯一的,不能让[0000 0000]【+0】[1000 0000]【-0】都来表示0.
      
    • 若机器码采用补码来计算,会是这样的结果:

          1-1 = 1 + (-1)= [0000 0001]【原】+[1000 0001]【原】= [0000 0001]【反】+[1111 1110]【反】= [0000 0001]【补】+[1111 1111]【补】= [0000 0000]【补】= [0000 0000]【原】= 0 【十进制】
          //这样保证了0的唯一性。
      
      
      还有一个额外的好处,若用原码、反码,取值范围都只限与[-127,127],但用补码是[-128,127]能多表示一个数-128。
      
          (-1)+(-127)= [1000 0001]【原】+[1111 1111]【原】= [1111 1110]【反】+ [1000 0000]【反】= [1111 1111]【补】+[1000 0001]【补】= [1000 0000]【补】
          //注意:-128在限定为8位时没有原码和反码,不信?那你将[1000 0000]【补】往原码进行转换,会得出[0000 0000]【原】,这明显错误!
      
      若机器采用补码表示有符号数,对于编程中常用32位的int类型,表数范围可以是[-2<sup>31</sup> , 2<sup>31</sup>-1],而不是原码的表数范围[-2<sup>31</sup>-1 , 2<sup>31</sup>-1]
      

四、如何将二进制补码还原为原码?

  1. 方法一:我们可以按原路返回,就是将计算机中存储的二进制补码减1,然后取反,再得到原码,换成相应负数即可,不过这样有点麻烦,因为涉及到了减法操作。

  2. 方法二:将负数的补码先取反,然后加1,最高位置换为1即可。

    对于-10,在计算机中存储为

    11111111 11111111 11111111 11110110 【补码形式】

    先取反,得

    00000000 00000000 00000000 00001001

    再加1,得

    00000000 00000000 00000000 00001010

    最高位变1,即

    10000000 00000000 00000000 00001010 【原码形式】

    结果是“-10”

五、奇技淫巧

1. 取反的快捷算法

~x等同于-(x+1)


10进制数2016,转32位2进制数为:

0000 0111 1110 0000

~按位取反:

1111 1000 0001 1111 【对应十进制数:-2017】

结果为:

(~2016) = -2017

六、参考资料

  1. 原码, 反码, 补码 详解 【这个大神太NB,把数学知识扯进来了,我有些看不明白,暂未将内容加入本文,后续看明白了补充进来】

  2. 按位取反运算符~ - 世朔 - 博客园

12-29 16:17