跳至主要內容

2.12 原码反码补码


原码反码补码

  • 计算机只能识别0和1, 所以计算机中存储的数据都是以0和1的形式存储的

  • 数据在计算机内部是以补码的形式储存的, 所有数据的运算都是以补码进行的

  • 正数的原码、反码和补码

    • 正数的原码、反码和补码都是它的二进制
    • 例如: 12的原码、反码和补码分别为
      • 0000 0000 0000 0000 0000 0000 0000 1100
      • 0000 0000 0000 0000 0000 0000 0000 1100
      • 0000 0000 0000 0000 0000 0000 0000 1100
  • 负数的原码、反码和补码

    • 二进制的最高位我们称之为符号位, 最高位是0代表是一个正数, 最高位是1代表是一个负数
    • 一个负数的原码, 是将该负数的二进制最高位变为1
    • 一个负数的反码, 是将该数的原码除了符号位以外的其它位取反
    • 一个负数的补码, 就是它的反码 + 1
    • 例如: -12的原码、反码和补码分别为
      0000 0000 0000 0000 0000 0000 0000 1100 // 12二进制
      1000 0000 0000 0000 0000 0000 0000 1100 // -12原码
      1111 1111 1111 1111 1111 1111 1111 0011  // -12反码
      1111 1111 1111 1111 1111 1111 1111 0100 // -12补码
    
  • 负数的原码、反码和补码逆向转换

    • 反码 = 补码-1
    • 原码= 反码最高位不变, 其它位取反
      1111 1111 1111 1111 1111 1111 1111 0100 // -12补码
      1111 1111 1111 1111 1111 1111 1111 0011  // -12反码
      1000 0000 0000 0000 0000 0000 0000 1100 // -12原码
    

  • 为什么要引入反码和补码

    • 在学习本节内容之前,大家必须明白一个东西, 就是计算机只能做加法运算, 不能做减法和乘除法, 所以的减法和乘除法内部都是用加法来实现的

      • 例如: 1 - 1, 内部其实就是 1 + (-1);
      • 例如: 3 * 3, 内部其实就是 3 + 3 + 3;
      • 例如: 9 / 3, 内部其实就是 9 + (-3) + (-3) + (-3);
    • 首先我们先来观察一下,如果只有原码会存储什么问题

      • 很明显, 通过我们的观察, 如果只有原码, 1-1的结果不对
        // 1 + 1
         0000 0000 0000 0000 0000 0000 0000 0001 // 1原码
        +0000 0000 0000 0000 0000 0000 0000 0001 // 1原码
         ---------------------------------------
         0000 0000 0000 0000 0000 0000 0000 0010  == 2
      
         // 1 - 1; 1 + (-1);
         0000 0000 0000 0000 0000 0000 0000 0001 // 1原码
        +1000 0000 0000 0000 0000 0000 0000 0001 // -1原码
         ---------------------------------------
         1000 0000 0000 0000 0000 0000 0000 0010 == -2
      
    • 正是因为对于减法来说,如果使用原码结果是不正确的, 所以才引入了反码
      • 通过反码计算减法的结果, 得到的也是一个反码;
      • 将计算的结果符号位不变其余位取反,就得到了计算结果的原码
      • 通过对原码的转换, 很明显我们计算的结果是-0, 符合我们的预期
      // 1 - 1; 1 + (-1);
      0000 0000 0000 0000 0000 0000 0000 0001 // 1反码
      1111 1111 1111 1111 1111 1111 1111 1110   // -1反码
      ---------------------------------------
      1111 1111 1111 1111 1111 1111 1111 1111 // 计算结果反码
      1000 0000 0000 0000 0000 0000 0000 0000 // 计算结果原码 == -0
    
    • 虽然反码能够满足我们的需求, 但是对于0来说, 前面的负号没有任何意义, 所以才引入了补码
      • 由于int只能存储4个字节, 也就是32位数据, 而计算的结果又33位, 所以最高位溢出了,符号位变成了0, 所以最终得到的结果是0
      // 1 - 1; 1 + (-1);
      0000 0000 0000 0000 0000 0000 0000 0001 // 1补码
      1111 1111 1111 1111 1111 1111 1111 1111   // -1补码
      ---------------------------------------
     10000 0000 0000 0000 0000 0000 0000 0000 // 计算结果补码
      0000 0000 0000 0000 0000 0000 0000 0000 //  == 0
    
上次编辑于: