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
- 虽然反码能够满足我们的需求, 但是对于0来说, 前面的负号没有任何意义, 所以才引入了补码