## 原码反码补码 - 计算机只能识别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** 拉你进学习交流群。 开源不易,码字不易,如果觉得有价值,欢迎分享支持。