📌 数据编码(原码 / 反码 / 补码)
所属等级:GESP 3级 | 难度: | 关键词:机器数、真值、原码、反码、补码、有符号、无符号
📝 考纲要求
- 理解机器数与真值的概念:机器数是计算机里真正存储的 0/1 串,真值是它代表的实际数值(带正负);
- 掌握原码 / 反码 / 补码三种编码的表示方法;
- 掌握负数的补码 = 反码 + 1 的变换规则;
- 理解为什么用补码:让加减法用同一套电路(统一成加法)、并让数字 0 只有一种表示;
- 掌握有符号与无符号整数的表示范围,特别是 8 位补码范围为
-128 ~ 127。
📖 通俗讲解
💡 一句话理解
计算机只认 0 和 1,但现实中有正数也有负数。为了把“负号”也装进二进制,人们约定最左边一位当作符号位(0 表示正、1 表示负),于是同一个数字就有了原码、反码、补码三种“写法”。正数三码相同,负数需要变换。
以 8 位(一个字节)为例来对照:最左边的第 1 位是符号位,后面 7 位是数值位。
- 原码:符号位 0/1 + 数值的二进制。最直白,但加减法麻烦,且 0 有
+0(00000000) 和-0(10000000) 两种。 - 反码:正数不变;负数的符号位不变、数值位按位取反(0 变 1,1 变 0)。
- 补码:正数的补码 = 原码;负数的补码 = 它的反码 + 1。计算机真正存储和运算用的就是补码。
下面用一张对照表看清 +5、-5、-1 在 8 位下的三种编码(注意 -1 的补码是全 1,也就是 11111111,当作无符号数看就是 255):
ASCII 图解
┌───────────┬────────────┬────────────┬────────────┐
│ 数值 │ 原码 │ 反码 │ 补码 │
├───────────┼────────────┼────────────┼────────────┤
│ +5 │ 0000 0101 │ 0000 0101 │ 0000 0101 │ 正数三码相同
│ -5 │ 1000 0101 │ 1111 1010 │ 1111 1011 │ 反码+1=补码
│ -1 │ 1000 0001 │ 1111 1110 │ 1111 1111 │ ★补码全1=255
└───────────┴────────────┴────────────┴────────────┘
符号位:0 正 / 1 负
正数:原码=反码=补码
负数:原码= 1 + 数值位
反码= 符号位不变,数值位取反
补码= 反码 + 1
-5 是怎么得到的?
① 原码:1 0000101 (符号位1,数值5=0000101)
② 反码:1 1111010 (数值位 0000101 取反 → 1111010)
③ 补码:1 1111011 (反码 +1 → 1111010 + 1 = 1111011)
-1 是怎么得到的?
① 原码:1 0000001
② 反码:1 1111110 (0000001 取反 → 1111110)
③ 补码:1 1111111 (反码 +1 → 1111110 + 1 = 1111111 = 全1)
下面用 C++ 把 -1 的 8 位补码真正打印出来,验证它确实是 11111111:
🖼️ 图解
8-bit: 最左 1 位是符号位(0 正 / 1 负)
+5 原码 0 0000101 = 反码 0 0000101 = 补码 0 0000101
-5 原码 1 0000101
反码 1 1111010 (符号位不变,数值位取反)
补码 1 1111011 (反码 + 1 = 补码)
+-------+-----------+-----------+-----------+
| num | 原码 | 反码 | 补码 |
+-------+-----------+-----------+-----------+
| +5 | 0000 0101 | 0000 0101 | 0000 0101 |
| -5 | 1000 0101 | 1111 1010 | 1111 1011 |
+-------+-----------+-----------+-----------+
正数三码相同;负数:补码 = 反码 + 1
C++
#include <iostream>
using namespace std;
int main() {
signed char a = -1; // 有符号字符,存的是 -1 的 8 位补码
unsigned char b = (unsigned char)a; // 把那 8 位当作“无符号”来看
cout << "有符号 -1 的 8 位补码:";
for (int i = 7; i >= 0; i--) // 从最高位到第 0 位依次输出
cout << ((b >> i) & 1);
cout << endl;
cout << "它当作无符号数时的值 = " << (int)b << endl; // 255
return 0;
}
输出有符号 -1 的 8 位补码:11111111
它当作无符号数时的值 = 255
🔵 核心必背重点
✅ 必背
- 正数三码相同:原码 = 反码 = 补码,符号位都是 0;
- 负数三步走:原码(符号位 1 + 数值位)→ 反码(符号位不变、数值位取反)→ 补码(反码 + 1);
- 8 位补码范围:
-128 ~ 127(共 256 个数);其中-128的补码是10000000,-1的补码是11111111; - 计算机用补码做加减法:减法变成“加一个负数”,一套加法电路搞定;
- 0 只有一种表示:补码里
00000000就是 0,没有-0。
🔑
记忆口诀:“正数三码一模一样;负数反码取反再 +1 得补码;补码全 1 是 -1,范围 -128 到 127;加加减减都用补码,正零负零合一 0。”
🔴 考试拉分难点
⚠️ 难点
- 为什么补码能统一加减法? 因为
a - b等价于a + (-b),而-b用补码表示后,直接做二进制加法、丢掉最高位的进位,结果正好正确(见例题 2)。 - 为什么 0 只有一种表示? 在原码里
+0(00000000) 和-0(10000000) 不同;而在补码里,-0的反码是11111111,加 1 后变成100000000,超出 8 位被截断,结果也是00000000,多出来的那个编码10000000就被用来表示-128。 - 有符号 vs 无符号范围:同样 8 位,
unsigned char范围是0 ~ 255,signed char范围是-128 ~ 127;同样是 256 个数,只是“切分”方式不同。
🟡 高频易错陷阱
🚫 扣分坑点
- 把原码当补码来加:用原码直接加
+5(00000101) + (-5)(10000101)会得到错误结果;必须先转成补码再相加。 - 忘记“反码 + 1”:负数补码不是只取反,取反后还要 +1,少一步就会算错(例如把
-1写成11111110就错了,正确是11111111)。 - 混淆有符号/无符号:
(unsigned char)-1打印出来是255,不是-1;面试和考试常考这个“绕回”。 - 写错范围:8 位有符号补码是
-128 ~ 127,不是-127 ~ 127,最小值是-128不是-127。
🧪 例题演练
例题 1(基础题):求 -1 的 8 位补码
题目:写出十进制数 -1 在 8 位补码下的二进制表示,并验证它当作无符号数时等于 255。
解答:按“负数三步走”:
① 原码 10000001;
② 反码(数值位取反)11111110;
③ 补码(反码 + 1)11111111。
所以 -1 的 8 位补码是 11111111,全 1;把它解释为无符号数就是 255。代码与上面基础讲解一致,输出为 11111111 和 255。
🚫 易错
常见错误答案是
10000001(那是原码)或 11111110(只取反没 +1)。记住:补码 = 反码 + 1,-1 的补码是全 1。
例题 2(模拟真题):用补码计算 5 + (-3)
题目:用 8 位补码计算 5 + (-3),写出二进制加法过程,结果应为 2。
解答:先写出两个数的 8 位补码:
ASCII 图解 · 补码加法
+5 的补码: 0 0000101 → 0000 0101
-3 的原码: 1 0000011
-3 的反码: 1 1111100 (数值位 0000011 取反)
-3 的补码: 1 1111101 (反码 +1)
二进制竖式(补码相加):
0000 0101 (+5)
+ 1111 1101 (-3 的补码)
───────────
1 0000 0010 ← 最高位进位 1 被丢弃
0000 0010 = 2 ✓
结论:5 + (-3) 用补码相加,丢掉进位后正好是 0000 0010 = 2。
C++
#include <iostream>
using namespace std;
int main() {
signed char a = 5; // 补码 0000 0101
signed char b = -3; // 补码 1111 1101
signed char c = a + b;
cout << "5 + (-3) = " << (int)c << endl; // 结果 2
return 0;
}
输出5 + (-3) = 2
🛡️ 避坑总结
- 正负数分开记:正数原/反/补三码相同;负数先写原码,再取反得反码,最后 +1 得补码;
- 补码 = 反码 + 1,这是负数变换的核心公式,少一步就错;
- -1 的补码是全 1(11111111),当作无符号数就是 255,这是高频考点;
- 8 位有符号补码范围 -128 ~ 127,最小值是 -128(补码 10000000),不是 -127;
- 计算机用补码做加减法,减法变加法,统一电路、0 只有一种表示;
- 区分有符号/无符号:同样 8 位,无符号是 0~255,有符号是 -128~127,负数强转无符号会发生“绕回”。
💡 提示:按 ← → 方向键可在上一 / 下一知识点间快速翻页