关于数据编码、进制、位运算的详细讲解(从属GESP三级)
本章内容
数据编码基础
进制转换
位运算基础
别让符号位绊住你的步伐,掌握补码,让加减法都成为加法。
一、 数据编码基础
目标:掌握 原码 / 反码 / 补码 的定义与互转、常见进制(2 / 8 / 10 / 16)互化方法,以及补码与位运算在实际运算中的意义与典型考点。
1 🧩 为什么需要 3 种编码?
编码 | 结构 | 主要特点 | 缺点 / 难点 | 卷面高频 |
原码 | 最高位为符号,剩余位为绝对值 | 真值直观,+0/-0 有两种表示 | 加减法需分正负两套电路 | 判断 ±0 |
反码 | 正数同原码;负数=符号位不变,其余位按位取反 | 减法可用加法+按位取反实现 | 仍有 ±0,并且要考虑进位回补 | “反码=补码?”判断 |
补码 | 正数同原码;负数=反码+1 | 唯一零 ,加减法统一,硬件最简单 | 表示范围不对称,最小负数无正值对应 | 范围、溢出、移位 |
记忆口诀
- • 原→反:符号位不动,其余取反
- • 反→补:末位 +1
2 🔍 数值范围与溢出
8 bit 有符号补码
- • 最大:0111 1111₂ = 127₁₀
- • 最小:1000 0000₂ = -128₁₀
判断补码加法溢出:符号位进位 ≠ 最高位进位 ➟ 溢出。考试常给二进制求和让你判断是否溢出。
3 📚 编码之间的快速互转
- 1. 十进制 → 原码
写出绝对值的二进制,最高位加符号位(0 正 1 负)。 - 2. 原码 → 反码 / 补码
负数才转换:原→反 取反,反→补 加1。 - 3. 补码 → 十进制
若符号位 0,直接转;为 1 时先求反码,再求原码,最后取值加负号。
4✏️ 进制转换秒法
方向 | 方法 | 例题(历届真题) |
16 → 8 | 先 16→2(4 位为 1 组),再 2→8(3 位为 1 组) | B2025₁₆ → 2620045₈ (2024-12 三级第 3 题) |
10 → 2(整数) | 连除 2 取余倒写 | 625₁₀ → 1001110001₂ (同卷第 4 题) |
10 → 2(小数) | 乘 2 取整顺写 | 0.8125₁₀ → 0.1101₂(2024-09 第 4 题) |
技巧
- • 2⇄8:三位一拍手;2⇄16:四位抱成团。
- • 带小数时,整数、⼩数部分分别转换再拼接。
5 📄 位运算与补码
运算 | 作用 | 典型考法 |
AND | 清 0 / 掩码提取 |
取低 4 位 |
` | ` OR | 置 1 / 合并标志 |
XOR | 取反 / 交换两数 | 见 2024-09 第 7 题“异或交换” |
NOT | 逐位取反 | 判断补码知识点 |
|
×2ⁿ, | 2024-12 第 6 题考负数右移 |
6 📁 历年高频考点总结
类别 | 高频问法 | 例 |
概念判断 | “负数的反码和补码是否一样?” | 2024-12 第 2 题 |
编码填空 | 给出 | 常见 8 bit 补码辨认 |
进制速算 | 二、八、十、十六互化 | 多次出现于 2023-06 / 2024-12 卷 |
位运算结果 |
对错判定 | 2024-12 第 5 题 |
移位与符号 | 负数右移后结果 | 2024-12 第 6 题 |
7 🔔 易错点 & 备考建议
- 1. ±0 混淆:补码只有一个 0;原码/反码有两个。
- 2. 符号扩展:带符号右移请保留符号位。
- 3. 最小负数:如 -128 (1000 0000₂) 取反再加 1 会溢出,务必牢记。
- 4. 小数二进制:乘 2 取整过程别漏 0。
- 5. 移位优先级:位运算优先级低于算术运算,必要时加括号。
刷题顺序
① 读大纲关键词 → ② 按年份把对应题目做一遍 → ③ 归类错因 → ④ 30 min 速刷补码计算与进制互化练习。
8 📊 课后 5 分钟快练
- 1. 8 bit 补码
1111 1011₂
表示的十进制数是? - 2. 把
0.375₁₀
写成二进制。 - 3. 判断:补码
1010 0000₂ >> 3
的结果是否仍为负数? - 4. 将
7C3₁₆
直接写成八进制。 - 5. 32-bit int
a
,执行a ^= (1<<5);
的作用是什么?
小结:数据编码是连接计算机硬件与程序语义的“翻译官”。熟练掌握 原/反/补码 与 进制转换,为后续位运算、整数溢出分析打下坚实基础。
二、进制转换
1 📌 进制概念一张表
基数 | 记号示例 | 用途/真题现身 |
二进制 (2) |
| 机器底层;真题常问“×××₁₀→₂” 或 “补码” |
八进制 (8) |
(前导 0) | 早期权限/颜色码;真题: |
十进制 (10) |
| 人类日常 |
十六进制 (16) |
| 汇编、颜色、补码展示;真题常给 16→10、16→8 |
2 📈 整数部分的转换算法
2.1 十进制 → 任意基 b
(除基取余)
vector<int> res;
while (N) { res.push_back(N % b); N /= b; }
reverse(res.begin(), res.end());
- • 真题代码填空:
decimal % 8; decimal /= 8;
(十转八)
2.2 2 → 8 / 16(分组法)
- • 每 3 位二进制 = 1 位八进制;每 4 位二进制 = 1 位十六进制。
- • 23 级单选专门考“由低到高分组”
2.3 8 / 16 → 2(反向分组)
- •
7
→111₂
、F
→1111₂
,再拼接;避免抄错高位补 0。
3 📉 小数部分的转换算法
方向 | 操作 | 真题示例 |
10 → 2/8/16 | 反复 乘基取整: |
|
2/8/16 → 10 | Σ(数字×基^-位次) |
(24-06-5) |
循环小数:若乘基后出现循环余数,则出现循环节;考场通常限制精度或给定可整除样例(如 0.625)。
4 🔗 补码与负数(真题必考)
步骤 | 8 位示例: |
原码 |
|
反码 | 负数:符号位不动,其余取反 → |
补码 | 反码 + 1 → |
考点 ① “补码简化硬件加减” 单选答案 B
考点 ② 补码范围:8 位有符号 -128~127
单选答案 A。
5 🖨️ C++ 常见实现与坑
5.1 标准库
功能 | 代码片段 |
字符串 → 整数 |
|
整数 → 不同进制输出 |
(真题填空选 |
现代 C++17 |
支持 2–36 基数 |
陷阱
- 1. 前缀
0
输入被cin
当 八进制。 - 2.
std::hex
会一直影响后续输出,记得cout<<std::dec;
恢复。
5.2 常用模板
string dec2hex(unsigned n){string s; const char *d="0123456789ABCDEF";do{ s.push_back(d[n&15]); n>>=4; }while(n);reverse(s.begin(),s.end()); return s;
}
6 ❌ 真题型“陷阱”速览
考法 | 代表题 | 关键点 |
速选结果 |
的二进制 | 整数、分数分别转换再合并(25-03-4) |
代码填空 | while 除 8 取余 | 递增 |
负数补码判断 | 8 位原/反/补对应 | 一位不同定律、符号位不动 |
“看位判断进制合法性” | 输出四列 0/1(23-09 编程) | 最大字符法快速判断可用进制 |
7 📄 速记口诀
“除基取余得整数,乘基取整求小数;三位八、四位十六,负数反补少一步!”
三、🔧 位运算基础
位运算(Bitwise Operation)=按二进制位直接进行的运算。
1 🎯 六大基本运算符
运算符 | 名称 | 二进制规则 |
| 按位 AND | 1 & 1 → 1,其余 → 0 |
` | ` | 按位 OR |
| 按位 XOR | 相同 → 0,不同 → 1 |
| 非 (取反) | 0 ↔ 1(单目) |
| 左移 | 整体向高位移,低位补 0 |
| 右移 | 整体向低位移,符号位复制(有符号)或补 0(无符号) |
优先级:~
> << >>
> &
> ^
> |
。常用括号防错。
2 💡 真值表速背
| A | B | A&B
| A|B
| A^B
|
|---|---|-------|-------|-------|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 1 | 1 |
| 1 | 1 | 1 | 1 | 0 |
3 🧪 常见“位技巧”模板
目标 | 公式 | 说明 |
取第 k 位 |
| 右移到最低位后与 1 相与 |
置 1 第 k 位 | `(n >> k) | 1` |
清 0 第 k 位 |
| |
翻转第 k 位 |
| |
判断奇偶 |
| 结果 0 → 偶,1 → 奇 |
低位快速乘 / 除 2ᵏ |
/ | 左移乘,右移除 |
4 🗂️ 典型真题拆解
真题问法 | 核心考点 | 一句答案 |
可实现什么? | 去最低位 1 | 清掉最右侧 1(25-03-选择) |
在 8 位结果? | 取反 |
|
的值? | 左移乘 2 | 10 |
| 逻辑右移 |
(即 3) |
的结果? | XOR 自反 | 0 |
5 📌 移位细节
- 1. 符号位复制
-
- •
int y = -8; y >> 1;
→ 仍为负(最高位补 1)。 - • 若想逻辑右移用 无符号:
unsigned(y) >> 1
。
- •
- 2. 超位宽移位
-
- •
x << 32
在 32-bit UB。考题常问“结果未定义”。
- •
- 3. 优先级
-
- •
a & 1 << k
⇒ 实际为a & (1<<k)
? 需加括号。
- •
6 🕒 小方法(真题改编)
// 统计整数 n 的二进制 1 的个数(Brian–Kernighan)
int popcount(int n){int cnt=0;while(n){n &= n-1; // 每次消掉最低 1cnt++;}return cnt;
}
// 真题:输入正整数,输出 1 的个数(24-12-编程)
// 交换变量最低两位
x = ((x & 1)<<1) | ((x & 2)>>1) | (x & ~3);
// 逻辑:提取第 0/1 位互换
7 ❌ 易错 TOP-4
易错 | 正确写法 |
|
|
忘记无符号逻辑右移 |
|
把 XOR 当 OR | XOR 只在不同位 1 |
超位宽移位 | 先转 |
8 ⭐ 速背口诀
与清零、或置位,异或翻转快如飞;移左乘、移右除,取位必须先括弧!
四、精选选择题 (10 题)
✅ 1. 【位运算 · 真题】
题目:设 unsigned x = 0xF0F0;
,表达式 x & 0x0FF0
的结果为
A. 0xF0F0
B. 0x00F0
C. 0x0F00
D. 0xFF00
答案:C
解析:
x = 1111 0000 1111 0000
mask = 0000 1111 1111 0000
AND = 0000 1111 0000 0000 = 0x0F00
【出自:24 年 6 月选择题 3】
✅ 2. 【位运算】
题目:要把变量 n
的第 5 位(从 0 开始计)清 0,可使用下列哪条语句?
A. n &= ~(1 << 5);
B. n |= ~(1 << 5);
C. n ^= ~(1 << 5);
D. n |= (1 << 5);
答案:A
解析:1<<5
得掩码 0x20
,取反后第 5 位为 0,其余位 1;与运算可清 0 指定位。
✅ 3. 【位运算 · 真题】
题目:对于正整数 n
,下列哪行代码可以快速判断 n
是否为 2 的整数次幂?
A. !(n & (n-1))
B. (n | (n-1)) == 0
C. (n ^ (n-1)) == 1
D. (n & (n+1)) == 0
答案:A
解析:若 n
为 2 的幂,则只有一个 1;n-1
把该 1 变成 0 且低位全 1,与运算结果为 0。
【出自:23 年 12 月选择题 6】
✅ 4. 【位运算】
题目:表达式 ((a & b) ^ (a | b))
等价于下列哪个选项?
A. ~a
B. a ^ b
C. a & (~b)
D. 0
答案:B
解析:集合恒等式:(A∩B) Δ (A∪B) = AΔB
。按位逻辑等同。
✅ 5. 【位运算 · 真题】
题目:在 32 位带符号整数中,-1 >> 1
的值为
A. 0x7FFFFFFF
B. 0xFFFFFFFF
C. 0x00000000
D. 0x80000000
答案:B
解析:算术右移,符号位 1 保持,所有位补 1,结果仍为 -1。
【出自:24 年 9 月选择题 5】
✅ 6. 【位运算】
题目:以下哪一行代码可以交换 x
、y
两整数而不使用临时变量?
A. x = x + y; y = x - y; x = x - y;
B. x ^= y; y ^= x; x ^= y;
C. x = (x & y) | (x & ~y);
D. x |= y; y |= x; x |= y;
答案:B
解析:三次异或交换经典 trick;A 有溢出风险。
✅ 7. 【位运算 · 真题】
题目:8 位补码 11010100₂
表示的十进制数是
A. -44 B. -44-1=-45 C. 44 D. 212
答案:A
解析:最高位 1 表负;求正值:~11010100+1=00101100=44
,故结果 -44
。
【出自:25 年 3 月选择题 7】
✅ 8. 【位运算】
题目:若 unsigned char c = 0b00101101;
,执行 c &= c-1;
后 c
的值为
A. 0b00101100
B. 0b00101110
C. 0b00101101
D. 0b00101001
答案:A
解析:c&(c-1)
清掉最低位 1。
✅ 9. 【位运算 · 真题】
题目:表达式 1 << 33
在 32 位编译环境下的行为是
A. 结果未定义(UB) B. 等于 0 C. 等于 2 D. 等于 4
答案:A
解析:移位位数 ≥ 类型宽度在 C++ 中属于未定义行为。
【出自:23 年 6 月选择题 11】
✅ 10. 【位运算】
题目:若想判断 x
是否为奇数,下列写法最有效率的是
A. x % 2 == 1
B. x & 1
C. x >> 1 << 1 != x
D. (x^1) == x+1
答案:B
解析:按位与 1 直接取最低位,复杂度最小。
五、精选判断题 (10 题)
✅ 1. 【位运算 · 真题】
题目:在 C++ 中,a ^ a
的结果恒为 0。
答案:对
解析:异或同值消 0。
【出自:24 年 12 月判断题 9】
✅ 2. 【位运算】
题目:对于任意 unsigned int n
,表达式 n << 1
等价于 n * 2
。
答案:对
解析:无符号左移一位相当于乘 2,且无溢出则数值相同。
✅ 3. 【位运算 · 真题】
题目:在 8 位补码中,~(0x00)
的值为 0xFF
。
答案:对
解析:按位取反,0→全 1。
【出自:23 年 9 月判断题 6】
✅ 4. 【位运算】
题目:若 x
与 x-1
按位与后结果为 0,则 x
一定是 2 的幂。
答案:对
解析:仅 2 的幂拥有单独 1 位。
✅ 5. 【位运算】
题目:在带符号右移中,高位补 0 和补 1 的行为由编译器决定,与数据类型无关。
答案:错
解析:带符号整数右移遵循算术右移,高位补符号位;无符号右移逻辑补 0。
✅ 6. 【位运算 · 真题】
题目:表达式 ~(~x)
恒等于 x
。
答案:对
解析:两次按位非相当于原值。
【出自:24 年 6 月判断题 8】
✅ 7. 【位运算】
题目:交换两个整数时,三次异或法会改变原有的位模式顺序。
答案:错
解析:异或交换不丢位,只互换变量值。
✅ 8. 【位运算 · 真题】
题目:表达式 x & (~x)
的值恒为 0。
答案:对
解析:x
与补码互补位无交集。
【出自:24 年 9 月判断题 10】
✅ 9. 【位运算】
题目:若 unsigned y = 1;
,则 (y >> 1) == 0
。
答案:对
解析:逻辑右移一位低位被抛弃,高位补 0,得到 0。
✅ 10. 【位运算】
题目:把 n &= (n-1)
连续执行 k
次可清除 n
二进制表示中最右侧 k
个 1。
答案:对
解析:每执行一次消掉一位最右 1,迭代 k 次即可。
六、 精选编程题
✅ 1. 【位运算 · 真题】
题目回顾:输入 32 位无符号整数 N
,输出其二进制中 1 的个数。
解题思路
- • 核心:利用
n &= n-1
每次消掉最低位 1,循环计数(Brian–Kernighan 算法)。 - • 复杂度:O(1) 空间,时间与 1 的个数成正比,最坏 32 次。
参考代码
#include <bits/stdc++.h>
using namespace std;int main() {uint32_t n;if (!(cin >> n)) return 0;int cnt = 0;while (n) {n &= (n - 1); // 消除最低位 1++cnt;}cout << cnt << '\n';return 0;
}
✅ 2. 【进制转换 · 编程】
题目回顾:将十进制正整数 X
转成基数 B
(2 / 8 / 16)并输出。
解题思路
- • 方法:对
X
反复X % B
记录余数,X /= B
更新,最后把余数逆序输出。 - • 字符映射:余数 0–15 映射到
"0123456789ABCDEF"
。 - • 复杂度:时间 O(log_B X),空间 O(log_B X) 存储结果字符。
参考代码
#include <bits/stdc++.h>
using namespace std;string convert(unsigned long long x, int base) {const char *dig = "0123456789ABCDEF";if (x == 0) return "0";string s;while (x) {s.push_back(dig[x % base]);x /= base;}reverse(s.begin(), s.end());return s;
}int main() {unsigned long long x; int b;if (!(cin >> x >> b)) return 0;cout << convert(x, b) << '\n';return 0;
}