zoukankan      html  css  js  c++  java
  • 【王的技法0001】机器数、真值、原码、反码、补码总结

    一、概念清单

    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. 意义:为了让符号位参与运算,以简化基础电路设计。

      人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了,于是人们开始探索 将符号位参与运算, 并且只保留加法的方法.

    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. 按位取反运算符~ - 世朔 - 博客园

  • 相关阅读:
    Linux命令之more
    Linux命令之sort
    STM32启动模式
    poll调用深入解析
    STM32 控制步进电机 28BYJ-48
    NEC协议
    家用宽带的上传和下载速度
    Ubuntu14.04更新源
    波特率和比特率【串口为例】
    CentOS: make menuconfig error: curses.h: No such file or directory
  • 原文地址:https://www.cnblogs.com/lanqingzhou/p/11888935.html
Copyright © 2011-2022 走看看