12.原码反码补码.md 3.9 KB
Newer Older
极客江南's avatar
极客江南 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
## 原码反码补码

- 计算机只能识别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的原码、反码和补码分别为

  ```c
    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
  - 原码= 反码最高位不变, 其它位取反

  ```c
    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的结果不对

    ```c
      // 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, 符合我们的预期

  ```c
    // 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

  ```c
    // 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
  ```

## 

最后,如果有任何疑问,请加微信 **leader_fengy** 拉你进学习交流群。

开源不易,码字不易,如果觉得有价值,欢迎分享支持。