02-📝物联网组网 | 数据传输基础-进制基础知识详解
📚 目录
- 一、进制的概念
- 二、常见进制系统
- 三、快速记忆技巧
- 四、进制转换方法
- 五、常见错误与注意事项
- 六、转换关系:Bit、Byte、二进制数、十六进制数
- 七、计算机中的进制应用
- 八、物联网中的进制应用
- 九、实际应用案例
- 十、练习题与解答
- 十一、快速转换表
- 十二、总结
- 十三、进阶学习
一、进制的概念
什么是进制?
进制(Number System),也称为数制或进位计数制,是一种表示数值的方法。它定义了:
-
基数(Base):表示该进制使用多少个不同的数字符号
-
位权(Positional Weight):每个位置上的数字所代表的实际值
进制的本质
任何进制都遵循以下规则:
数值 = Σ(每一位数字 × 该位的位权)
其中,位权 = 基数的位置次方(从右到左,从0开始)
进制的表示方法
在数学和计算机科学中,通常用下标表示进制:
-
1010₂ 或 (1010)₂ - 二进制
-
123₈ 或 (123)₈ - 八进制
-
456₁₀ 或 456 - 十进制(默认)
-
ABC₁₆ 或 0xABC - 十六进制
二、常见进制系统
1. 十进制(Decimal System)
基数:10
数字符号: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
位权: 10⁰, 10¹, 10², 10³, ...
示例:
1234₁₀ = 1×10³ + 2×10² + 3×10¹ + 4×10⁰
= 1×1000 + 2×100 + 3×10 + 4×1
= 1000 + 200 + 30 + 4
= 1234
特点:
- 人类最常用的计数系统
- 符合人类十根手指的计数习惯
- 日常生活中的所有数字都是十进制
2. 二进制(Binary System)
基数:2
数字符号: 0, 1
位权: 2⁰, 2¹, 2², 2³, ...
示例:
1011₂ = 1×2³ + 0×2² + 1×2¹ + 1×2⁰
= 1×8 + 0×4 + 1×2 + 1×1
= 8 + 0 + 2 + 1
= 11₁₀
特点:
- 计算机的基础语言
- 只有两个状态,对应电路的开关(0/1)
- 所有数字信息最终都以二进制形式存储和处理
二进制与十进制的对应关系:
| 二进制 |
十进制 |
二进制 |
十进制 |
| 0 |
0 |
1000 |
8 |
| 1 |
1 |
1001 |
9 |
| 10 |
2 |
1010 |
10 |
| 11 |
3 |
1011 |
11 |
| 100 |
4 |
1100 |
12 |
| 101 |
5 |
1101 |
13 |
| 110 |
6 |
1110 |
14 |
| 111 |
7 |
1111 |
15 |
3. 八进制(Octal System)
基数:8
数字符号: 0, 1, 2, 3, 4, 5, 6, 7
位权: 8⁰, 8¹, 8², 8³, ...
示例:
123₈ = 1×8² + 2×8¹ + 3×8⁰
= 1×64 + 2×8 + 3×1
= 64 + 16 + 3
= 83₁₀
特点:
- 在Unix/Linux文件权限中常用
- 一个八进制位对应三个二进制位
- 便于表示二进制数据(3位一组)
八进制与二进制的对应关系:
| 八进制 |
二进制 |
八进制 |
二进制 |
| 0 |
000 |
4 |
100 |
| 1 |
001 |
5 |
101 |
| 2 |
010 |
6 |
110 |
| 3 |
011 |
7 |
111 |
4. 十六进制(Hexadecimal System)
基数:16
数字符号: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
位权: 16⁰, 16¹, 16², 16³, ...
字母对应:
- A = 10
- B = 11
- C = 12
- D = 13
- E = 14
- F = 15
示例:
A3F₁₆ = A×16² + 3×16¹ + F×16⁰
= 10×256 + 3×16 + 15×1
= 2560 + 48 + 15
= 2623₁₀
特点:
- 计算机科学中最常用的非十进制进制
- 一个十六进制位对应四个二进制位
- 便于表示内存地址、颜色值等
- 比二进制更紧凑,比十进制更直观
十六进制与二进制的对应关系:
| 十六进制 |
二进制 |
十六进制 |
二进制 |
| 0 |
0000 |
8 |
1000 |
| 1 |
0001 |
9 |
1001 |
| 2 |
0010 |
A |
1010 |
| 3 |
0011 |
B |
1011 |
| 4 |
0100 |
C |
1100 |
| 5 |
0101 |
D |
1101 |
| 6 |
0110 |
E |
1110 |
| 7 |
0111 |
F |
1111 |
三、快速记忆技巧
二进制转十六进制口诀
"四位一组,对应一位"
示例:
1011 0101 → B 5 → 0xB5
1111 0000 → F 0 → 0xF0
常用2的幂次方记忆
2⁰=1, 2¹=2, 2²=4, 2³=8, 2⁴=16, 2⁵=32, 2⁶=64, 2⁷=128, 2⁸=256
记忆:1, 2, 4, 8, 16, 32, 64, 128, 256(翻倍规律)
快速计算技巧:
- 2¹⁰ = 1024 ≈ 1000(1KB)
- 2²⁰ = 1,048,576 ≈ 100万(1MB)
- 2³⁰ = 1,073,741,824 ≈ 10亿(1GB)
十六进制字母对应记忆
A=10, B=11, C=12, D=13, E=14, F=15
记忆:A是10,之后按字母顺序递增
记忆口诀:
- "A是10,B是11,C是12,D是13,E是14,F是15"
- "A到F,10到15,字母顺序就是数字顺序"
二进制转八进制口诀
"三位一组,对应一位"
示例:
101 101 → 5 5 → 55₈
111 001 011 → 7 1 3 → 713₈
十进制转二进制快速法
"不断除以2,倒序取余"
示例:45₁₀ → 二进制
45 ÷ 2 = 22 ... 1
22 ÷ 2 = 11 ... 0
11 ÷ 2 = 5 ... 1
5 ÷ 2 = 2 ... 1
2 ÷ 2 = 1 ... 0
1 ÷ 2 = 0 ... 1
从下往上读:101101₂
四、进制转换方法
1. 其他进制 → 十进制
方法:按权展开求和
公式:
N进制数 = dₙ×Nⁿ + dₙ₋₁×Nⁿ⁻¹ + ... + d₁×N¹ + d₀×N⁰
示例1:二进制转十进制
101101₂ = 1×2⁵ + 0×2⁴ + 1×2³ + 1×2² + 0×2¹ + 1×2⁰
= 1×32 + 0×16 + 1×8 + 1×4 + 0×2 + 1×1
= 32 + 0 + 8 + 4 + 0 + 1
= 45₁₀
示例2:八进制转十进制
347₈ = 3×8² + 4×8¹ + 7×8⁰
= 3×64 + 4×8 + 7×1
= 192 + 32 + 7
= 231₁₀
示例3:十六进制转十进制
2A5₁₆ = 2×16² + A×16¹ + 5×16⁰
= 2×256 + 10×16 + 5×1
= 512 + 160 + 5
= 677₁₀
2. 十进制 → 其他进制
方法:除基取余法(倒序排列)
步骤:
- 用目标进制基数连续除以十进制数
- 记录每次的余数
- 直到商为0
- 将余数倒序排列
示例1:十进制转二进制
转换 45₁₀ 为二进制:
45 ÷ 2 = 22 ... 余 1 ← 最低位
22 ÷ 2 = 11 ... 余 0
11 ÷ 2 = 5 ... 余 1
5 ÷ 2 = 2 ... 余 1
2 ÷ 2 = 1 ... 余 0
1 ÷ 2 = 0 ... 余 1 ← 最高位
结果:45₁₀ = 101101₂
示例2:十进制转八进制
转换 231₁₀ 为八进制:
231 ÷ 8 = 28 ... 余 7 ← 最低位
28 ÷ 8 = 3 ... 余 4
3 ÷ 8 = 0 ... 余 3 ← 最高位
结果:231₁₀ = 347₈
示例3:十进制转十六进制
转换 677₁₀ 为十六进制:
677 ÷ 16 = 42 ... 余 5 ← 最低位
42 ÷ 16 = 2 ... 余 10 (A)
2 ÷ 16 = 0 ... 余 2 ← 最高位
结果:677₁₀ = 2A5₁₆
3. 二进制 ↔ 八进制
方法:三位一组
二进制 → 八进制:
- 从右到左,每3位二进制数为一组
- 不足3位时,左边补0
- 每组转换为对应的八进制数
示例:
101101₂ → 八进制
分组:101 101
↓ ↓
5 5
结果:101101₂ = 55₈
八进制 → 二进制:
- 每位八进制数转换为3位二进制数
- 不足3位时,左边补0
示例:
347₈ → 二进制
3 → 011
4 → 100
7 → 111
结果:347₈ = 011100111₂ = 11100111₂
4. 二进制 ↔ 十六进制
方法:四位一组
二进制 → 十六进制:
- 从右到左,每4位二进制数为一组
- 不足4位时,左边补0
- 每组转换为对应的十六进制数
示例:
101101₂ → 十六进制
分组:0010 1101
↓ ↓
2 D
结果:101101₂ = 2D₁₆
十六进制 → 二进制:
- 每位十六进制数转换为4位二进制数
- 不足4位时,左边补0
示例:
2A5₁₆ → 二进制
2 → 0010
A → 1010
5 → 0101
结果:2A5₁₆ = 001010100101₂ = 1010100101₂
5. 八进制 ↔ 十六进制
方法:通过二进制作为中间进制
步骤:
- 先转换为二进制
- 再转换为目标进制
示例:
347₈ → 十六进制
步骤1:347₈ = 11100111₂
步骤2:11100111₂ = 1110 0111 = E7₁₆
结果:347₈ = E7₁₆
6. 进制转换可视化示例
二进制转十六进制可视化
二进制: 1 0 1 1 0 1 0 1
分组: [1 0 1 1] [0 1 0 1]
位权: 8 4 2 1 8 4 2 1
计算: 8+0+2+1 0+4+0+1
结果: 11(B) 5
十六进制: B 5
十进制转二进制可视化
转换 45₁₀ 为二进制:
步骤可视化:
45 ÷ 2 = 22 ... 余 1 ← 最低位(LSB)
22 ÷ 2 = 11 ... 余 0
11 ÷ 2 = 5 ... 余 1
5 ÷ 2 = 2 ... 余 1
2 ÷ 2 = 1 ... 余 0
1 ÷ 2 = 0 ... 余 1 ← 最高位(MSB)
从下往上读取余数:101101₂
五、常见错误与注意事项
1. 进制转换常见错误
错误1:忘记补零
错误示例:
101₂ → 八进制
错误:直接分组为 1 01(不足3位)
正确:补零后分组为 001 01 = 15₈
错误示例:
1011₂ → 十六进制
错误:直接分组为 101 1(不足4位)
正确:补零后分组为 1011 = B₁₆
错误2:混淆位权方向
错误示例:
1011₂ 的计算
错误:从左边开始计算位权(1×2⁰ + 0×2¹ + 1×2² + 1×2³)
正确:从右边开始,从0开始计数(1×2³ + 0×2² + 1×2¹ + 1×2⁰)
记忆技巧: 位权从右到左,从0开始递增
错误3:十六进制字母大小写混淆
注意:
-
0xABC 和 0xabc 表示同一个值
- 但通常约定使用大写字母(A-F)
- 在某些编程语言中,大小写可能影响解析
错误4:八进制与十进制混淆
危险示例:
// C语言中,0开头的数字会被解释为八进制
int x = 0123; // 这是八进制,等于 83₁₀,不是 123₁₀
int y = 123; // 这是十进制,等于 123₁₀
注意: 在编程时,避免使用0开头的数字,除非明确需要八进制
2. 进制表示法的注意事项
二进制表示注意事项
-
避免前导零混淆:
0101 可能被误认为是八进制
-
明确标注:使用
1010₂ 或 0b1010 明确表示二进制
-
补零规则:在分组转换时,从右到左分组,不足位数在左边补0
十六进制表示注意事项
-
必须使用前缀或下标:
FF 可能被误认为是变量名
-
标准表示:
- 编程中:
0xFF 或 0xff
- 数学中:
FF₁₆ 或 (FF)₁₆
-
字母大小写:虽然大小写等价,但建议统一使用大写
八进制表示注意事项
-
0前缀陷阱:在编程语言中,
0123 会被解释为八进制
-
明确标注:使用
123₈ 或 0o123 明确表示八进制
-
应用场景:主要用于Unix/Linux文件权限,其他场景较少使用
3. 转换过程中的常见陷阱
陷阱1:小数转换
注意: 本文主要讨论整数转换。小数转换需要不同的方法:
0.1₁₀ = 0.00011001100110011...₂(无限循环)
小数转换需要:
- 整数部分:除基取余法
- 小数部分:乘基取整法
陷阱2:负数转换
注意: 负数需要使用补码表示,不能直接转换:
-5₁₀ ≠ 直接转换二进制
-5₁₀ = 11111011₂(8位补码)
详见"进阶学习"部分的补码章节。
陷阱3:溢出问题
注意: 不同位数的表示范围不同:
8位二进制:0-255(无符号)或 -128到127(有符号)
16位二进制:0-65535(无符号)或 -32768到32767(有符号)
超出范围会导致溢出,结果不正确。
4. 实际应用中的注意事项
字节序问题
注意: 多字节数据在不同系统中存储顺序可能不同:
0x12345678 在不同系统中的存储:
大端序:12 34 56 78
小端序:78 56 34 12
详见"进阶学习"部分的字节序章节。
数据对齐问题
注意: 某些系统要求数据按特定字节边界对齐:
32位系统:数据通常按4字节对齐
64位系统:数据通常按8字节对齐
六、转换关系:Bit、Byte、二进制数、十六进制数
核心关系总结
- Bit(比特)是最小单位
- Byte(字节)是基础存储单位;
-
字节由固定数量的比特组成
- 二进制数是比特的直接表现形式
- 十六进制数是二进制数的“简化书写形式”(每4位二进制对应1位十六进制)。
逐概念拆解+关联
-
Bit(比特)
计算机中最小的信息单位,只有0和1两种状态(对应二进制的一位),比如“1”或“0”就是1个Bit。
-
Byte(字节)
计算机的基础存储单位,1个Byte = 8个Bit(固定换算)。
例:1 Byte 对应 8位二进制数(如 01011010),这是字节与比特、二进制的核心关联。
-
二进制数
仅由0、1组成的数(底层本质),1位二进制数 = 1 Bit,8位二进制数 = 1 Byte。
因二进制数位数多(如16位二进制是 1111000011110000),书写/阅读麻烦,衍生出十六进制简化。
-
十六进制数
由0-9、A-F(对应10-15)组成,1位十六进制数 = 4位二进制数(核心换算),因此:
- 2位十六进制数 = 8位二进制数 = 1 Byte;
- 例:二进制 10101100 → 拆分为 1010 + 1100 → 对应十六进制 AC(10=A,12=C)。
极简示例
1 Byte(字节)= 8 Bit(比特)= 8位二进制数(10101100)= 2位十六进制数(AC)。
七、计算机中的进制应用
1. 数据存储单位
位(Bit):二进制的最小单位,0或1
字节(Byte):8位二进制数 = 1字节
常见单位换算:
1 Byte = 8 bits
1 KB = 1024 Bytes = 2¹⁰ Bytes
1 MB = 1024 KB = 2²⁰ Bytes
1 GB = 1024 MB = 2³⁰ Bytes
1 TB = 1024 GB = 2⁴⁰ Bytes
2. 内存地址表示
内存地址通常用十六进制表示:
0x00000000 - 内存起始地址
0x0000FFFF - 64KB内存的结束地址
0xFFFFFFFF - 32位系统的最大地址(4GB)
3. 颜色表示
RGB颜色值用十六进制表示:
#FF0000 - 红色(R=255, G=0, B=0)
#00FF00 - 绿色(R=0, G=255, B=0)
#0000FF - 蓝色(R=0, G=0, B=255)
#FFFFFF - 白色(R=255, G=255, B=255)
#000000 - 黑色(R=0, G=0, B=0)
转换示例:
#FF5733 = RGB(255, 87, 51)
FF₁₆ = 255₁₀
57₁₆ = 87₁₀
33₁₆ = 51₁₀
4. 文件权限(Unix/Linux)
八进制表示文件权限:
rwx rwx rwx
421 421 421
权限位:
- r (read) = 4
- w (write) = 2
- x (execute) = 1
示例:
755₈ = rwxr-xr-x
= 111 101 101₂
= 所有者:读写执行,组:读执行,其他:读执行
644₈ = rw-r--r--
= 110 100 100₂
= 所有者:读写,组:读,其他:读
5. 字符编码
ASCII码:
- 用7位二进制(0-127)表示128个字符
- 常用字符的ASCII码:
- '0' = 48₁₀ = 30₁₆
- 'A' = 65₁₀ = 41₁₆
- 'a' = 97₁₀ = 61₁₆
Unicode:
- UTF-8:可变长度编码,1-4字节
- UTF-16:2或4字节
- UTF-32:固定4字节
八、物联网中的进制应用
1. 设备地址(MAC地址)
MAC地址用十六进制表示:
格式:XX:XX:XX:XX:XX:XX
示例:00:1B:44:11:3A:B7
每段范围:00-FF(0-255)
总长度:48位(6字节)
转换示例:
MAC: 00:1B:44:11:3A:B7
00₁₆ = 00000000₂ = 0₁₀
1B₁₆ = 00011011₂ = 27₁₀
44₁₆ = 01000100₂ = 68₁₀
11₁₆ = 00010001₂ = 17₁₀
3A₁₆ = 00111010₂ = 58₁₀
B7₁₆ = 10110111₂ = 183₁₀
2. IP地址表示
IPv4地址:
点分十进制:192.168.1.1
二进制: 11000000.10101000.00000001.00000001
十六进制: 0xC0A80101
IPv6地址(十六进制):
格式:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX
示例:2001:0db8:85a3:0000:0000:8a2e:0370:7334
简写:2001:db8:85a3::8a2e:370:7334
3. 传感器数据
温度传感器数据(16位二进制):
原始数据:0x0190 (十六进制)
二进制: 0000000110010000
十进制: 400
实际温度:40.0°C(假设精度为0.1°C)
湿度传感器数据:
原始数据:0x00C8 (十六进制)
二进制: 0000000011001000
十进制: 200
实际湿度:50.0%RH(假设精度为0.5%RH)
4. 通信协议数据包
BLE(蓝牙低功耗)数据包格式:
数据包结构(十六进制表示):
[前缀][地址][长度][数据][校验]
示例:
02 01 06 03 03 AA FE 11 16 AA FE 10 00 01 02 03 04 05
02 - 长度
01 - AD类型(Flags)
06 - 值(LE General Discoverable)
03 - 长度
03 - AD类型(16-bit Service UUIDs)
AA FE - UUID
...
5. 固件版本号
版本号用十六进制编码:
版本 1.2.3 可能编码为:
0x010203
01₁₆ = 1₁₀ (主版本)
02₁₆ = 2₁₀ (次版本)
03₁₆ = 3₁₀ (修订版本)
6. 设备ID和序列号
设备唯一标识符:
64位设备ID(十六进制):
0x1234567890ABCDEF
转换为二进制:
0001001000110100010101100111100010010000101010111100110111101111
7. 数据包解析实战
场景: 解析一个完整的BLE数据包
原始数据(十六进制):
02 01 06 05 16 AA FE 10 00 01 02 03 04
逐字节解析:
字节0 (0x02): AD结构长度(2字节)
字节1 (0x01): AD类型(Flags)
字节2 (0x06): 标志值
- 0x06 = 00000110₂
- Bit 1: LE General Discoverable (1)
- Bit 2: BR/EDR Not Supported (1)
字节3 (0x05): AD结构长度(5字节)
字节4 (0x16): AD类型(Service Data - 16-bit UUID)
字节5-6 (0xAA 0xFE): UUID(0xFEAA,iBeacon标准UUID)
字节7 (0x10): 主版本号(0x10₁₆ = 16₁₀)
字节8 (0x00): 次版本号(0x00₁₆ = 0₁₀)
字节9-12 (0x01 0x02 0x03 0x04): 自定义数据
完整解析结果:
- 设备类型:iBeacon
- 版本:16.0
- 自定义数据:0x01020304
8. 常见物联网协议中的进制应用
Modbus协议
功能码(十六进制):
0x01 - 读线圈状态
0x02 - 读离散输入状态
0x03 - 读保持寄存器
0x04 - 读输入寄存器
0x05 - 写单个线圈
0x06 - 写单个寄存器
0x0F - 写多个线圈
0x10 - 写多个寄存器
寄存器地址(十六进制):
地址范围:0x0000 - 0xFFFF(16位,65536个寄存器)
示例:0x0001, 0x0010, 0x0100, 0xFFFF
数据格式示例:
请求帧:01 03 00 00 00 0A C5 CD
解析:
01 - 设备地址(1)
03 - 功能码(读保持寄存器)
00 00 - 起始地址(0)
00 0A - 寄存器数量(10)
C5 CD - CRC校验
CoAP协议
消息格式(二进制位):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver| T | TKL | Code | Message ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
代码字段(8位):
前3位:类别(0-7)
- 0: 请求
- 2: 成功响应
- 4: 客户端错误
- 5: 服务器错误
后5位:详情(0-31)
- 0.01: GET请求
- 2.05: 内容响应
- 4.04: 未找到
MQTT协议
固定报头(二进制):
Bit: 7 6 5 4 3 2 1 0
[Message Type][Flags][Remaining Length]
消息类型(4位):
0000: 保留
0001: CONNECT
0010: CONNACK
0011: PUBLISH
0100: PUBACK
0101: PUBREC
0110: PUBREL
0111: PUBCOMP
1000: SUBSCRIBE
1001: SUBACK
1010: UNSUBSCRIBE
1011: UNSUBACK
1100: PINGREQ
1101: PINGRESP
1110: DISCONNECT
1111: 保留
LoRaWAN协议
设备地址(32位,十六进制):
格式:0xXXXXXXXX
示例:0x12345678
范围:0x00000000 - 0xFFFFFFFF
帧计数器(16位,十六进制):
格式:0xXXXX
示例:0x0001, 0x00FF, 0x0100
范围:0x0000 - 0xFFFF(65535)
9. 传感器数据编码格式
温度传感器(DS18B20)
数据格式(16位,二进制):
Bit: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
[符号位][温度整数部分(11位)][小数部分(4位)]
示例:
原始数据:0x0190 (十六进制)
二进制: 0000000110010000
解析:
- 符号位:0(正数)
- 整数部分:00000011001 = 25₁₀
- 小数部分:0000 = 0
结果:25.0°C
湿度传感器(SHT30)
数据格式(16位,十六进制):
温度:0xXXXX(16位,大端序)
湿度:0xXXXX(16位,大端序)
转换公式:
温度 = (数据值 / 65535) × 175 - 45
湿度 = (数据值 / 65535) × 100
示例:
温度数据:0x6E80
十进制:28288
温度 = (28288 / 65535) × 175 - 45 = 30.5°C
湿度数据:0x4CCC
十进制:19660
湿度 = (19660 / 65535) × 100 = 30.0%RH
九、实际应用案例
案例1:BLE设备数据解析
场景: 解析BLE温度传感器的数据
原始数据(十六进制):
0x19 0x64 0x01 0x00
解析过程:
字节0 (0x19): 温度整数部分
0x19₁₆ = 25₁₀
字节1 (0x64): 温度小数部分
0x64₁₆ = 100₁₀
小数 = 100 / 100 = 1.0
字节2-3 (0x0100): 湿度值
0x0100₁₆ = 256₁₀
湿度 = 256 / 10 = 25.6%RH
结果:温度 = 25.1°C,湿度 = 25.6%RH
案例2:WiFi配置数据编码
场景: 将WiFi SSID和密码编码为十六进制
SSID: "MyHome"
ASCII编码:
M = 0x4D
y = 0x79
H = 0x48
o = 0x6F
m = 0x6D
e = 0x65
结果:0x4D 0x79 0x48 0x6F 0x6D 0x65
密码: "12345678"
ASCII编码:
1 = 0x31
2 = 0x32
3 = 0x33
4 = 0x34
5 = 0x35
6 = 0x36
7 = 0x37
8 = 0x38
结果:0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38
案例3:MQTT消息编码
场景: 设备控制命令编码
命令:打开第3号设备,亮度50%
设备ID:3 (0x03)
命令:打开 (0x01)
亮度:50 (0x32)
消息包:
[0x03][0x01][0x32]
二进制表示:
00000011 00000001 00110010
案例4:CRC校验计算
场景: 计算数据包的CRC校验值
数据: 0x12 0x34 0x56
CRC-8计算(简化示例):
使用多项式:x⁸ + x² + x + 1 (0x07)
计算过程(二进制运算):
数据:00010010 00110100 01010110
...
CRC结果:0xAB
十、练习题与解答
练习题1:进制转换
题目:
- 将
10110110₂ 转换为十进制
- 将
255₁₀ 转换为二进制和十六进制
- 将
A3F₁₆ 转换为二进制和八进制
解答:
1. 二进制转十进制:
10110110₂ = 1×2⁷ + 0×2⁶ + 1×2⁵ + 1×2⁴ + 0×2³ + 1×2² + 1×2¹ + 0×2⁰
= 128 + 0 + 32 + 16 + 0 + 4 + 2 + 0
= 182₁₀
2. 十进制转二进制和十六进制:
255 ÷ 2 = 127 ... 余 1
127 ÷ 2 = 63 ... 余 1
63 ÷ 2 = 31 ... 余 1
31 ÷ 2 = 15 ... 余 1
15 ÷ 2 = 7 ... 余 1
7 ÷ 2 = 3 ... 余 1
3 ÷ 2 = 1 ... 余 1
1 ÷ 2 = 0 ... 余 1
255₁₀ = 11111111₂
11111111₂ = FF₁₆(每4位一组:1111 1111 = F F)
3. 十六进制转二进制和八进制:
A3F₁₆ = A(1010) 3(0011) F(1111) = 101000111111₂
二进制转八进制(每3位一组):
101000111111₂ = 101 000 111 111 = 5077₈
练习题2:实际应用
题目:
一个BLE设备发送的数据包为:0x02 0x19 0x64 0x01
已知:
- 字节0 (0x02):数据长度
- 字节1 (0x19):温度值(整数部分)
- 字节2 (0x64):温度值(小数部分,除以100)
- 字节3 (0x01):状态(0=关闭,1=开启)
请解析这个数据包。
解答:
数据长度:0x02₁₆ = 2₁₀(表示后面有2个数据字节)
温度整数部分:0x19₁₆ = 25₁₀
温度小数部分:0x64₁₆ = 100₁₀ ÷ 100 = 1.0
实际温度:25.1°C
状态:0x01₁₆ = 1₁₀ = 开启
解析结果:
- 数据长度:2字节
- 温度:25.1°C
- 状态:开启
练习题3:IP地址转换
题目:
将IP地址 192.168.1.100 转换为:
- 二进制表示
- 十六进制表示
解答:
1. 转换为二进制:
192₁₀ = 11000000₂
168₁₀ = 10101000₂
1₁₀ = 00000001₂
100₁₀ = 01100100₂
结果:11000000.10101000.00000001.01100100
2. 转换为十六进制:
192₁₀ = C0₁₆
168₁₀ = A8₁₆
1₁₀ = 01₁₆
100₁₀ = 64₁₆
结果:0xC0A80164
练习题4:文件权限
题目:
将文件权限 rwxr-xr-x 转换为:
- 八进制表示
- 二进制表示
解答:
权限分解:
rwx r-x r-x
421 401 401
1. 八进制表示:
所有者:rwx = 4+2+1 = 7
组: r-x = 4+0+1 = 5
其他: r-x = 4+0+1 = 5
结果:755₈
2. 二进制表示:
7 = 111₂
5 = 101₂
5 = 101₂
结果:111101101₂
练习题5:错误纠正
题目: 找出以下转换中的错误并改正
-
101₂ = 5₁₀ ✓ 正确
-
0xFF = 255₁₀ ✓ 正确
-
256₁₀ = 0x100 ✓ 正确
-
1010₂ = 0xA ✗ 错误:应该是 0x0A(需要补零)
-
123₈ = 123₁₀ ✗ 错误:123₈ = 83₁₀(八进制,不是十进制)
-
0x1A = 26₁₀ ✓ 正确
-
1111₂ = 15₁₀ ✓ 正确
-
0x100 = 256₁₀ ✓ 正确
改正说明:
- 第4题:二进制转十六进制时,不足4位需要在左边补0
- 第5题:八进制数不能直接当作十进制数,需要转换
练习题6:综合应用
题目:
一个物联网设备发送了以下数据包(十六进制):
02 03 00 19 64 01 00 FF
数据包格式:
- 字节0:数据包类型(0x02 = 传感器数据)
- 字节1:数据长度(后续数据字节数)
- 字节2-3:设备ID(16位,大端序)
- 字节4:温度整数部分
- 字节5:温度小数部分(除以100)
- 字节6:状态标志位
- 字节7:校验和
请完成以下任务:
- 解析设备ID(转换为十进制)
- 计算实际温度值
- 解析状态标志位(每个bit代表一个状态)
- 验证校验和(所有数据字节的异或值)
解答:
1. 解析设备ID:
字节2-3:0x00 0x19(大端序)
0x0019₁₆ = 25₁₀
设备ID:25
2. 计算温度:
温度整数部分:0x64₁₆ = 100₁₀
温度小数部分:0x01₁₆ = 1₁₀ ÷ 100 = 0.01
实际温度:100.01°C
3. 解析状态标志位:
状态字节:0x00₁₆ = 00000000₂
所有状态位都是0,表示:
- Bit 0: 设备关闭
- Bit 1: WiFi未连接
- Bit 2: BLE未连接
- Bit 3: 传感器异常
- Bit 4-7: 保留位
4. 验证校验和:
数据字节:0x03 0x00 0x19 0x64 0x01 0x00
异或运算:
0x03 ^ 0x00 ^ 0x19 ^ 0x64 ^ 0x01 ^ 0x00
= 0x03 ^ 0x19 ^ 0x64 ^ 0x01
= 0x1A ^ 0x64 ^ 0x01
= 0x7E ^ 0x01
= 0x7F
校验和:0x7F
接收到的校验和:0xFF
校验失败!数据包可能损坏。
练习题7:多进制转换综合
题目:
将数值 186₁₀ 转换为:
- 二进制(8位和16位)
- 八进制
- 十六进制
- 验证所有转换结果的一致性
解答:
1. 转换为二进制:
186 ÷ 2 = 93 ... 0
93 ÷ 2 = 46 ... 1
46 ÷ 2 = 23 ... 0
23 ÷ 2 = 11 ... 1
11 ÷ 2 = 5 ... 1
5 ÷ 2 = 2 ... 1
2 ÷ 2 = 1 ... 0
1 ÷ 2 = 0 ... 1
186₁₀ = 10111010₂(8位)
186₁₀ = 0000000010111010₂(16位,补零)
2. 转换为八进制:
方法1:通过二进制
10111010₂ = 010 111 010 = 272₈
方法2:直接除8
186 ÷ 8 = 23 ... 2
23 ÷ 8 = 2 ... 7
2 ÷ 8 = 0 ... 2
186₁₀ = 272₈
3. 转换为十六进制:
方法1:通过二进制
10111010₂ = 1011 1010 = BA₁₆
方法2:直接除16
186 ÷ 16 = 11 ... 10 (A)
11 ÷ 16 = 0 ... 11 (B)
186₁₀ = 0xBA
4. 验证一致性:
二进制:10111010₂
= 1×2⁷ + 0×2⁶ + 1×2⁵ + 1×2⁴ + 1×2³ + 0×2² + 1×2¹ + 0×2⁰
= 128 + 0 + 32 + 16 + 8 + 0 + 2 + 0
= 186₁₀ ✓
八进制:272₈
= 2×8² + 7×8¹ + 2×8⁰
= 128 + 56 + 2
= 186₁₀ ✓
十六进制:0xBA
= B×16¹ + A×16⁰
= 11×16 + 10×1
= 176 + 10
= 186₁₀ ✓
所有转换结果一致!
练习题8:实际场景应用
题目:
你正在开发一个智能家居系统,需要处理以下场景:
场景1: 解析温湿度传感器的数据
- 原始数据:
0x0190 0x00C8(两个16位值,大端序)
- 温度公式:
温度 = 数据值 / 10
- 湿度公式:
湿度 = 数据值 / 2
场景2: 编码控制命令
- 设备地址:15(0x0F)
- 命令类型:打开(0x01)
- 参数值:128(0x80)
- 需要生成完整的命令包:
[地址][命令][参数]
场景3: 计算数据包大小
- 一个数据包包含:1字节类型 + 2字节长度 + N字节数据 + 1字节校验
- 如果数据部分有50字节,总包大小是多少?
- 用二进制、十进制、十六进制分别表示
请完成以上三个场景的计算。
解答:
场景1:解析传感器数据
温度数据:0x0190
0x0190₁₆ = 400₁₀
温度 = 400 / 10 = 40.0°C
湿度数据:0x00C8
0x00C8₁₆ = 200₁₀
湿度 = 200 / 2 = 100.0%RH(注意:可能超出正常范围)
场景2:编码控制命令
设备地址:15 = 0x0F
命令类型:打开 = 0x01
参数值:128 = 0x80
命令包:[0x0F][0x01][0x80]
完整命令:0x0F 0x01 0x80
场景3:计算数据包大小
数据部分:50字节
总包大小 = 1 + 2 + 50 + 1 = 54字节
二进制:54₁₀ = 110110₂
十进制:54
十六进制:54₁₀ = 0x36
验证:
110110₂ = 32 + 16 + 4 + 2 = 54₁₀ ✓
0x36 = 3×16 + 6 = 48 + 6 = 54₁₀ ✓
十一、快速转换表
常用十进制、二进制、十六进制对照表
| 十进制 |
二进制 |
十六进制 |
八进制 |
| 0 |
0000 |
0 |
0 |
| 1 |
0001 |
1 |
1 |
| 2 |
0010 |
2 |
2 |
| 3 |
0011 |
3 |
3 |
| 4 |
0100 |
4 |
4 |
| 5 |
0101 |
5 |
5 |
| 6 |
0110 |
6 |
6 |
| 7 |
0111 |
7 |
7 |
| 8 |
1000 |
8 |
10 |
| 9 |
1001 |
9 |
11 |
| 10 |
1010 |
A |
12 |
| 11 |
1011 |
B |
13 |
| 12 |
1100 |
C |
14 |
| 13 |
1101 |
D |
15 |
| 14 |
1110 |
E |
16 |
| 15 |
1111 |
F |
17 |
| 16 |
10000 |
10 |
20 |
| 32 |
100000 |
20 |
40 |
| 64 |
1000000 |
40 |
100 |
| 128 |
10000000 |
80 |
200 |
| 255 |
11111111 |
FF |
377 |
2的幂次方表
| 2的n次方 |
十进制值 |
十六进制 |
应用场景 |
| 2⁰ |
1 |
0x01 |
最小单位 |
| 2¹ |
2 |
0x02 |
二进制位 |
| 2² |
4 |
0x04 |
半字节 |
| 2³ |
8 |
0x08 |
1字节 |
| 2⁴ |
16 |
0x10 |
十六进制 |
| 2⁵ |
32 |
0x20 |
字符编码 |
| 2⁶ |
64 |
0x40 |
Base64 |
| 2⁷ |
128 |
0x80 |
ASCII |
| 2⁸ |
256 |
0x100 |
1字节最大值 |
| 2¹⁰ |
1024 |
0x400 |
1KB |
| 2¹⁶ |
65536 |
0x10000 |
2字节最大值 |
| 2²⁰ |
1048576 |
0x100000 |
1MB |
| 2³² |
4294967296 |
0x100000000 |
4字节最大值 |
十二、总结
核心要点
-
进制本质:不同进制只是表示数值的不同方式,本质是相同的
-
转换方法:
- 其他进制→十进制:按权展开
- 十进制→其他进制:除基取余
- 二进制↔八进制:三位一组
- 二进制↔十六进制:四位一组
-
应用场景:
- 二进制:计算机底层,数据存储
- 八进制:Unix文件权限
- 十六进制:内存地址,颜色值,设备地址
- 十进制:日常使用
学习建议
-
熟记常用转换:0-15的二进制、十六进制对应关系
-
掌握转换方法:理解原理,熟练运用
-
实际应用练习:通过物联网项目加深理解
-
工具辅助:使用计算器验证,但理解原理更重要
进制系统对比总结
| 进制 |
基数 |
数字符号 |
主要应用 |
优势 |
劣势 |
| 二进制 |
2 |
0,1 |
计算机底层、数据存储 |
硬件实现简单、直接对应电路状态 |
表示冗长、不易阅读 |
| 八进制 |
8 |
0-7 |
Unix/Linux文件权限 |
与二进制转换方便(3位一组) |
应用场景较少 |
| 十进制 |
10 |
0-9 |
日常使用、数学计算 |
符合人类习惯、直观 |
与二进制转换复杂 |
| 十六进制 |
16 |
0-9,A-F |
编程、调试、内存地址、设备地址 |
紧凑易读、与二进制转换方便(4位一组) |
需要记忆字母对应关系 |
实用工具推荐
在线工具
进制转换器:
程序员计算器:
-
Windows计算器(程序员模式)
- 路径:开始菜单 → 计算器 → 菜单 → 程序员
- 支持:二进制、八进制、十进制、十六进制
- 支持位运算操作
- 实时转换显示
-
macOS计算器(程序员模式)
- 路径:应用程序 → 计算器 → 显示 → 程序员
- 功能类似Windows计算器
编程语言中的进制表示
Python:
# 进制转换
bin(255) # '0b11111111' (二进制)
oct(255) # '0o377' (八进制)
hex(255) # '0xff' (十六进制)
# 字符串转数值
int('11111111', 2) # 255 (二进制转十进制)
int('377', 8) # 255 (八进制转十进制)
int('FF', 16) # 255 (十六进制转十进制)
# 格式化输出
format(255, 'b') # '11111111' (二进制字符串)
format(255, 'o') # '377' (八进制字符串)
format(255, 'x') # 'ff' (十六进制字符串,小写)
format(255, 'X') # 'FF' (十六进制字符串,大写)
format(255, '08b') # '11111111' (8位二进制,补零)
JavaScript:
// 进制转换
(255).toString(2) // '11111111' (二进制)
(255).toString(8) // '377' (八进制)
(255).toString(16) // 'ff' (十六进制)
// 字符串转数值
parseInt('11111111', 2) // 255 (二进制转十进制)
parseInt('377', 8) // 255 (八进制转十进制)
parseInt('FF', 16) // 255 (十六进制转十进制)
// 十六进制字面量
0xFF // 255
0b11111111 // 255 (ES6+)
0o377 // 255 (ES6+)
C/C++:
// 进制字面量
int x = 0xFF; // 十六进制
int y = 0377; // 八进制(注意:0开头)
int z = 0b11111111; // 二进制(C99+,部分编译器支持)
// 格式化输出
printf("%d\n", 255); // 十进制:255
printf("%o\n", 255); // 八进制:377
printf("%x\n", 255); // 十六进制:ff(小写)
printf("%X\n", 255); // 十六进制:FF(大写)
printf("%#x\n", 255); // 十六进制:0xff(带前缀)
// 字符串转数值
strtol("FF", NULL, 16); // 255
strtol("377", NULL, 8); // 255
strtol("11111111", NULL, 2); // 255
Java:
// 进制转换
Integer.toBinaryString(255); // "11111111"
Integer.toOctalString(255); // "377"
Integer.toHexString(255); // "ff"
// 字符串转数值
Integer.parseInt("11111111", 2); // 255
Integer.parseInt("377", 8); // 255
Integer.parseInt("FF", 16); // 255
// 进制字面量
int x = 0xFF; // 十六进制
int y = 0377; // 八进制(注意:0开头)
int z = 0b11111111; // 二进制(Java 7+)
Go:
// 进制转换
strconv.FormatInt(255, 2) // "11111111"
strconv.FormatInt(255, 8) // "377"
strconv.FormatInt(255, 16) // "ff"
// 字符串转数值
strconv.ParseInt("11111111", 2, 64) // 255
strconv.ParseInt("377", 8, 64) // 255
strconv.ParseInt("FF", 16, 64) // 255
// 格式化输出
fmt.Printf("%b\n", 255) // 二进制:11111111
fmt.Printf("%o\n", 255) // 八进制:377
fmt.Printf("%x\n", 255) // 十六进制:ff
fmt.Printf("%X\n", 255) // 十六进制:FF
推荐的学习工具
1. 进制转换练习网站
- 提供随机题目练习
- 即时反馈和解答
- 适合初学者巩固基础
2. 十六进制编辑器
-
HxD (Windows)
-
Hex Fiend (macOS)
-
Bless (Linux)
- 用途:查看和编辑二进制文件,理解数据在内存中的表示
3. 网络抓包工具
-
Wireshark:分析网络数据包,查看十六进制数据
-
tcpdump:命令行抓包工具
- 用途:实际应用中的进制数据解析
4. 调试工具
-
GDB (GNU Debugger):查看内存中的十六进制数据
-
LLDB:macOS/iOS调试工具
- 用途:理解程序运行时数据的进制表示
十三、进阶学习
💡 提示:以下内容适合已掌握基础进制转换的读者。建议先完成前面的练习题,再学习进阶内容。
学习路径建议
阶段1:基础掌握(必学)
- ✅ 理解进制概念和本质
- ✅ 掌握常见进制系统(二、八、十、十六进制)
- ✅ 熟练进行进制转换
- ✅ 理解Bit、Byte、二进制、十六进制的关系
- ✅ 完成所有基础练习题
阶段2:中级进阶(推荐)
- 📖 负数的表示(补码)
- 📖 字节序(大端序/小端序)
- 📖 位运算操作
- 📖 实际应用场景练习
阶段3:高级应用(可选)
- 🔬 浮点数表示(IEEE 754)
- 🔬 数据压缩和编码
- 🔬 深入理解计算机底层原理
学习建议:
- 按阶段循序渐进,不要跳跃学习
- 每个阶段都要通过实践练习巩固
- 结合实际项目应用,加深理解
- 遇到困难时,回到基础部分复习
1. 负数的表示(补码)
在计算机中,负数通常使用**补码(Two's Complement)**来表示,这是目前最常用的有符号整数表示方法。
为什么使用补码?
- 统一了加法和减法运算(减法可以转换为加法)
- 消除了正零和负零的问题(只有一个零)
- 简化了硬件实现
补码的规则:
-
正数:补码 = 原码(二进制表示)
-
负数:补码 = 反码 + 1
计算步骤(以8位为例):
示例:-5 的补码表示
步骤1:写出 +5 的二进制
+5₁₀ = 00000101₂
步骤2:取反(得到反码)
~00000101 = 11111010₂
步骤3:加1(得到补码)
11111010 + 1 = 11111011₂
结果:-5₁₀ = 11111011₂(补码)
验证:
+5₁₀ = 00000101₂
-5₁₀ = 11111011₂
相加:00000101 + 11111011 = 100000000₂(溢出,结果为0)
补码的范围:
- 8位:-128 到 +127
- 16位:-32768 到 +32767
- 32位:-2147483648 到 +2147483647
快速计算负数补码:
方法:从右到左,找到第一个1,保持这个1及其右边的所有位不变,
将左边的所有位取反。
示例:-5 = 11111011₂
从右到左第一个1在位置0,保持11111011不变
示例:-20 = ?
+20 = 00010100₂
从右到左第一个1在位置2,保持100不变,左边取反
结果:11101100₂
2. 浮点数的表示(IEEE 754)
IEEE 754是浮点数表示的国际标准,定义了单精度(32位)和双精度(64位)浮点数的格式。
单精度浮点数(32位)结构:
[符号位 1位][指数位 8位][尾数位 23位]
示例:-12.5 的IEEE 754表示
步骤1:转换为二进制
12.5₁₀ = 1100.1₂
步骤2:规范化(科学计数法)
1100.1₂ = 1.1001₂ × 2³
步骤3:提取各部分
符号位:1(负数)
指数:3 + 127 = 130₁₀ = 10000010₂(偏移127)
尾数:1001(去掉前导1,补0到23位)
结果:1 10000010 10010000000000000000000
双精度浮点数(64位)结构:
[符号位 1位][指数位 11位][尾数位 52位]
指数偏移:1023
特殊值:
-
零:指数和尾数全为0
-
无穷大:指数全为1,尾数全为0
-
NaN(非数字):指数全为1,尾数非0
精度问题:
0.1 + 0.2 ≠ 0.3(在二进制浮点数中)
原因:0.1 和 0.2 无法精确表示为二进制小数
0.1₁₀ = 0.00011001100110011...₂(无限循环)
3. 大端序和小端序(字节序)
字节序(Endianness) 是指多字节数据在内存中的存储顺序。
大端序(Big-Endian):
- 高位字节存储在低地址
- 符合人类阅读习惯
- 网络传输标准(网络字节序)
- 使用平台:PowerPC、SPARC、网络协议
小端序(Little-Endian):
- 低位字节存储在低地址
- 便于硬件实现
- 使用平台:x86、ARM(可配置)
示例:
数值:0x12345678(32位)
大端序存储(地址从低到高):
地址: 0x1000 0x1001 0x1002 0x1003
数据: 12 34 56 78
小端序存储(地址从低到高):
地址: 0x1000 0x1001 0x1002 0x1003
数据: 78 56 34 12
判断字节序的方法:
// C语言示例
int x = 0x12345678;
char *p = (char *)&x;
if (p[0] == 0x78) {
// 小端序
} else {
// 大端序
}
网络字节序转换:
网络传输统一使用大端序(Big-Endian)
转换函数(C语言):
- htons():主机序转网络序(16位)
- ntohs():网络序转主机序(16位)
- htonl():主机序转网络序(32位)
- ntohl():网络序转主机序(32位)
4. 位运算操作
位运算直接操作二进制位,是底层编程的重要工具。
基本位运算:
| 运算符 |
名称 |
说明 |
示例 |
& |
按位与 |
两个位都为1时结果为1 |
1010 & 1100 = 1000 |
| |
按位或 |
两个位有一个为1时结果为1 |
1010 | 1100 = 1110 |
^ |
按位异或 |
两个位不同时结果为1 |
1010 ^ 1100 = 0110 |
~ |
按位取反 |
0变1,1变0 |
~1010 = 0101 |
<< |
左移 |
向左移动,右边补0 |
1010 << 2 = 101000 |
>> |
右移 |
向右移动,左边补符号位或0 |
1010 >> 2 = 0010 |
常用位运算技巧:
1. 判断奇偶数:
n & 1 == 0 // 偶数
n & 1 == 1 // 奇数
2. 快速乘除2的幂:
n << k // 等于 n × 2ᵏ
n >> k // 等于 n ÷ 2ᵏ(向下取整)
3. 交换两个数(不使用临时变量):
a = a ^ b
b = a ^ b // b = (a ^ b) ^ b = a
a = a ^ b // a = (a ^ b) ^ a = b
4. 检查第k位是否为1:
(n >> k) & 1
5. 设置第k位为1:
n | (1 << k)
6. 清除第k位(设为0):
n & ~(1 << k)
7. 切换第k位:
n ^ (1 << k)
8. 获取最低位的1:
n & -n // 或 n & (~n + 1)
9. 清除最低位的1:
n & (n - 1)
10. 计算1的个数(汉明重量):
// 方法1:循环
count = 0
while n:
count += n & 1
n >>= 1
// 方法2:Brian Kernighan算法
count = 0
while n:
n &= n - 1
count += 1
位运算在物联网中的应用:
// 设备状态标志位
#define STATUS_POWER_ON 0x01 // 00000001
#define STATUS_WIFI_CONN 0x02 // 00000010
#define STATUS_BLE_CONN 0x04 // 00000100
#define STATUS_SENSOR_OK 0x08 // 00001000
// 设置状态
status |= STATUS_POWER_ON | STATUS_WIFI_CONN;
// 清除状态
status &= ~STATUS_BLE_CONN;
// 检查状态
if (status & STATUS_WIFI_CONN) {
// WiFi已连接
}
5. 数据压缩和编码
数据压缩通过减少数据表示所需的位数来节省存储空间和传输带宽。
1. 霍夫曼编码(Huffman Coding)
- 变长编码,频率高的字符用短码,频率低的用长码
- 前缀码:任何字符的编码都不是另一个字符编码的前缀
- 应用:ZIP、JPEG、MP3等
示例:
字符频率:
A: 50%, B: 30%, C: 15%, D: 5%
霍夫曼树构建:
(100%)
/ \
A(50%) (50%)
/ \
B(30%) (20%)
/ \
C(15%) D(5%)
编码结果:
A: 0
B: 10
C: 110
D: 111
平均码长:1×0.5 + 2×0.3 + 3×0.15 + 3×0.05 = 1.7位
固定码长:2位(需要4个不同编码)
压缩率:1.7/2 = 85%
2. 游程编码(Run-Length Encoding, RLE)
- 将连续相同的数据用"数据+重复次数"表示
- 适用于有大量连续重复数据的场景
示例:
原始数据:AAAAABBBCCCCCC
编码:A5B3C6
原始:11111111000000111111
编码:1(8)0(7)1(6)
3. 字典编码(LZ系列)
- LZ77、LZ78、LZW等
- 用字典中的索引替换重复出现的字符串
- 应用:GIF、PNG、ZIP等
4. Base64编码
- 将二进制数据编码为ASCII字符
- 每3个字节(24位)编码为4个字符(每个字符6位)
- 字符集:A-Z, a-z, 0-9, +, /
示例:
原始数据:Man
二进制:01001101 01100001 01101110
分组(6位一组):
010011 010110 000101 101110
转换为Base64:
010011 = 19 = T
010110 = 22 = W
000101 = 5 = F
101110 = 46 = u
结果:TWFu
5. 物联网中的压缩应用
传感器数据压缩:
// 温度数据:25.1, 25.2, 25.3, 25.4, 25.5
// 使用差分编码
原始:25.1, 25.2, 25.3, 25.4, 25.5
差分:25.1, +0.1, +0.1, +0.1, +0.1
// 只需要存储第一个值和增量
MQTT消息压缩:
// 原始JSON
{"device":"sensor01","temp":25.1,"humidity":60}
// 压缩后(自定义二进制格式)
[设备ID:1字节][温度:2字节][湿度:1字节]
0x01 0x019B 0x3C
图像压缩:
- JPEG:有损压缩,适用于照片
- PNG:无损压缩,适用于图标、截图
- WebP:现代格式,兼顾质量和大小
视频压缩:
- H.264/H.265:视频编码标准
- 帧间压缩:利用相邻帧的相似性
- 关键帧(I帧)、预测帧(P帧)、双向预测帧(B帧)
压缩比计算:
压缩比 = 原始大小 / 压缩后大小
示例:
原始:1000字节
压缩后:300字节
压缩比:1000/300 = 3.33:1
压缩率 = (1 - 压缩后大小/原始大小) × 100%
压缩率 = (1 - 300/1000) × 100% = 70%
选择压缩算法的考虑因素:
-
压缩比:能压缩多少
-
压缩速度:压缩需要多长时间
-
解压速度:解压需要多长时间
-
是否可逆:无损 vs 有损
-
CPU/内存消耗:资源占用情况
实践项目建议
通过实际项目可以加深对进制知识的理解和应用。以下项目按难度递增排列:
初级项目
项目1:进制转换器
目标: 开发一个支持多进制互转的工具
功能要求:
- 支持二进制、八进制、十进制、十六进制之间的相互转换
- 输入验证和错误处理
- 显示转换过程和步骤
- 支持大数转换
技术栈: Python/JavaScript/任何你熟悉的语言
学习重点:
- 实现各种进制转换算法
- 理解不同进制的表示方法
- 处理边界情况和错误输入
项目2:数据包解析器
目标: 解析BLE或WiFi数据包
功能要求:
- 读取十六进制格式的数据包
- 解析数据包结构(头部、数据、校验)
- 显示解析结果(温度、湿度、设备ID等)
- 验证校验和
技术栈: Python/JavaScript
学习重点:
- 理解数据包格式
- 掌握字节序处理
- 实践十六进制数据解析
项目3:文件权限查看器
目标: 显示文件的八进制权限和二进制权限
功能要求:
- 读取文件权限
- 转换为八进制和二进制表示
- 显示权限的详细说明(rwx格式)
技术栈: Python/Shell脚本
学习重点:
- 理解Unix文件权限系统
- 掌握八进制和二进制转换
- 理解位运算的应用
中级项目
项目4:物联网数据采集系统
目标: 处理传感器数据(涉及进制转换)
功能要求:
- 接收传感器原始数据(十六进制)
- 解析温度、湿度、压力等传感器数据
- 数据格式转换和单位换算
- 数据存储和可视化
技术栈: Python + Flask/Django + 数据库
学习重点:
- 实际物联网数据格式
- 大端序/小端序处理
- 数据精度和单位转换
项目5:网络协议分析工具
目标: 解析TCP/IP数据包
功能要求:
- 捕获网络数据包
- 解析IP头部、TCP头部
- 显示十六进制和ASCII格式的数据
- 分析协议字段
技术栈: Python + Scapy / C + libpcap
学习重点:
项目6:内存查看器
目标: 查看和编辑内存中的十六进制数据
功能要求:
- 以十六进制格式显示内存内容
- 支持搜索和替换
- 显示ASCII字符
- 支持不同数据类型的解析(int, float, string)
技术栈: C/C++ / Python
学习重点:
高级项目
项目7:数据压缩工具
目标: 实现简单的压缩算法
功能要求:
- 实现RLE(游程编码)压缩
- 实现简单的霍夫曼编码
- 计算压缩比
- 支持压缩和解压缩
技术栈: Python/C/C++
学习重点:
项目8:嵌入式系统调试工具
目标: 内存查看、寄存器操作
功能要求:
- 通过串口/USB连接嵌入式设备
- 读取和写入内存(十六进制格式)
- 读取和修改寄存器值
- 显示寄存器位字段含义
技术栈: Python + PySerial / C
学习重点:
项目9:协议实现
目标: 实现一个简单的物联网协议
功能要求:
- 设计数据包格式(使用二进制/十六进制)
- 实现数据编码和解码
- 实现校验和计算
- 支持多设备通信
技术栈: Python/C/C++
学习重点:
项目开发建议
-
从简单开始:先完成初级项目,再挑战中级和高级项目
-
注重实践:理论结合实践,通过项目加深理解
-
代码规范:注意代码可读性和注释
-
测试验证:编写测试用例,验证转换结果的正确性
-
文档记录:记录开发过程和遇到的问题
-
开源分享:将项目开源,获得反馈和改进建议
学习资源
-
GitHub:搜索相关项目,学习他人实现
-
Stack Overflow:遇到问题及时查找解决方案
-
技术博客:阅读相关技术文章,了解最佳实践
-
在线课程:系统学习相关技术栈
参考资料:
- 《计算机组成原理》
- 《数字电路基础》
- IEEE 754 浮点数标准
- ASCII/Unicode 字符编码标准