← 返回学习中心ARC LAB / LEARNING NOTES

建立共同基础

计算机基础

计算机组成、进制、编码、存储单位与位运算。

展开本篇目录

一、为什么学习计算机基础?

编写程序、配置环境和处理数据时,经常会遇到下面的问题:

  • 内存和硬盘有什么区别?程序运行时 CPU 在做什么?
  • 0b1010、10 和 0xA 为什么表示同一个数?
  • 为什么一个汉字不一定只占两个字节?
  • 100 Mbps 的网络为什么不等于每秒下载 100 MB?
  • 位运算怎样检查一个设备状态或提取一段数据?

本教程从计算机组成出发,介绍数值、字符和文件在计算机中的基本表示方法,并通过手算与 Python 示例验证结果。

说明: 不会 Python 也可以先阅读概念和手算示例。代码用于辅助验证,不需要记住全部函数;涉及固定宽度数据时,会明确标注位数。

二、计算机的基本组成

2.1 五类基本部件

传统计算机组成常用运算器、控制器、存储器、输入设备和输出设备来描述。

部件 主要作用 示例
运算器 算术运算与逻辑运算 CPU 中的算术逻辑单元 ALU
控制器 组织指令执行,协调各部件 CPU 中的控制逻辑
存储器 保存指令与数据 内存、缓存、外部存储设备
输入设备 将外部信息送入计算机 键盘、鼠标、传感器
输出设备 将处理结果送到外部 显示器、打印机、指示灯

现代 CPU 除运算和控制部件外,还包含寄存器、缓存等结构。网卡、触摸屏和存储设备等也可能同时承担输入与输出功能。

2.2 CPU、内存与硬盘

名称 主要用途 常见特点
CPU 执行指令、处理数据 内含一个或多个核心
寄存器 保存正在处理的少量数据与状态 容量小、访问快
缓存 Cache 减少 CPU 等待主存的时间 常见 L1、L2、L3 等层级
内存 RAM 保存运行中的程序和数据 常见主存断电后不保留数据
SSD / HDD 长期保存程序和文件 通常断电后仍能保留数据

“内存不够”和“硬盘空间不够”是两种问题。前者可能影响同时运行的程序和数据规模,后者影响能保存多少文件。

容量、速度和价格存在权衡,不能只看某一个指标判断性能。CPU 主频也不能单独决定不同计算机的运行速度。

2.3 程序怎样运行?

以运行一个数据处理程序为例:

存储设备中的程序与数据
↓ 操作系统和运行环境组织加载
内存中的指令与数据
↓ CPU 取指令、译码、执行
处理结果写回内存
↓
显示结果或保存到文件

这是简化过程。实际系统还涉及缓存、虚拟内存、中断和设备控制器等机制;Python 程序还需要解释器参与执行。

2.4 总线与操作系统

总线或其他互连用于传递数据、地址和控制信息。操作系统负责管理进程、内存、文件和设备,为应用程序提供运行与访问资源的接口。

“64 位系统”与处理器、指令集和软件的数据模型有关,不表示所有数据都占 64 位,也不表示一定能实际使用 2^64 字节内存。

三、bit、Byte 与二进制

3.1 bit:二进制位

bit 中文常称“位”或“比特”,表示一个二进制位置,其取值可以是 0 或 1。

电路可以用可区分的物理状态表示它们。逻辑上的 0 和 1 不应简单理解为所有设备中都完全相同的电压值。

3.2 Byte:字节

现代通用计算机中,1 Byte(字节,记作 B)通常等于 8 bit。本教程均按这一约定计算:

1 B = 8 bit
2 B = 16 bit
4 B = 32 bit
8 B = 64 bit

大小写有区别:b 常用于位,B 用于字节。描述数据速率时常见 bit/s、Mbps 和 MB/s。

3.3 n 位能表示多少种状态?

每位有两种取值,n 位共有 2^n 种组合。

1 位:2 种,0、1
2 位:4 种,00、01、10、11
8 位:256 种

如果按无符号整数解释,n 位的范围是 0 到 2^n - 1。例如 8 位无符号整数为 0~255,不是 1~256。

四、二、八、十、十六进制的表示

4.1 什么是进制?

进制规定每一位可用的数字,以及向高位进位的规则。基数为 r 的进制,每向左一位,位权乘以 r。

进制 基数 可用数字 示例
二进制 2 0、1 (1010)₂
八进制 8 0~7 (12)₈
十进制 10 0~9 (10)₁₀
十六进制 16 0~9、A~F (A)₁₆

十六进制中的 A、B、C、D、E、F 分别对应十进制 10、11、12、13、14、15,字母大小写均常见。

4.2 位权

十进制 253 可以展开为:

253 = 2×10² + 5×10¹ + 3×10⁰

二进制整数从右向左的位权为:

位权:128 64 32 16 8 4 2 1
数字: 0 0 1 0 1 1 0 1

4.3 编程中的前缀

Python 中常用下面的前缀区分整数写法:

print(0b1010)  # 二进制,输出 10
print(0o12) # 八进制,输出 10
print(10) # 十进制,输出 10
print(0xA) # 十六进制,输出 10

这些写法表示同一个整数。进制改变的是表示方式,不改变数值本身。

注意: Python 的八进制前缀是 0o,不是直接在十进制数字前加 0。其他语言的规则可能不同。

五、其他进制转换为十进制

采用“各位数字乘位权,再求和”的方法。

5.1 二进制转十进制

(101101)₂
= 1×2⁵ + 0×2⁴ + 1×2³ + 1×2² + 0×2¹ + 1×2⁰
= 32 + 8 + 4 + 1
= (45)₁₀

5.2 八进制转十进制

(157)₈
= 1×8² + 5×8¹ + 7×8⁰
= 64 + 40 + 7
= (111)₁₀

5.3 十六进制转十进制

(2F)₁₆
= 2×16¹ + 15×16⁰
= 32 + 15
= (47)₁₀

检查时注意数字是否合法,例如八进制不能含 8,二进制不能含 2。

六、十进制转换为其他进制

6.1 整数:除基取余,逆序排列

把非负十进制整数转换为 r 进制时,反复除以 r,记录余数,直到商为 0,再将余数从后往前排列。

以十进制 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
所以 (45)₁₀ = (101101)₂

6.2 十进制转八进制

111 ÷ 8 = 13 余 7
13 ÷ 8 = 1 余 5
1 ÷ 8 = 0 余 1

(111)₁₀ = (157)₈

6.3 十进制转十六进制

255 ÷ 16 = 15 余 15 → F
15 ÷ 16 = 0 余 15 → F

(255)₁₀ = (FF)₁₆

余数大于 9 时,用 A~F 表示。数字 0 转换后仍为 0,不需要执行多次除法。

七、二进制、八进制与十六进制互转

7.1 二进制与八进制

因为 8 = 2³,一位八进制对应三位二进制。

八进制 二进制 八进制 二进制
0 000 4 100
1 001 5 101
2 010 6 110
3 011 7 111

整数部分从右向左每三位分组,不足三位在左侧补零:

101101 → 101 101 → 5 5 → (55)₈

反向转换时,将每个八进制数字展开成三位二进制:

(157)₈ → 001 101 111 → (1101111)₂

7.2 二进制与十六进制

因为 16 = 2⁴,一位十六进制对应四位二进制。

十六进制 二进制 十六进制 二进制
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
101101 → 0010 1101 → 2 D → (2D)₁₆
(AF)₁₆ → 1010 1111 → (10101111)₂

7.3 八进制与十六进制

可以通过二进制中转:

(157)₈
→ 001 101 111
→ 0110 1111
→ (6F)₁₆

补零只用于补齐分组,不改变数值。固定宽度的数据中,前导零还可以帮助表达位数,例如 00001111 表示按 8 位展示。

八、小数的进制转换

8.1 二进制小数转十进制

小数点右侧的位权为 2⁻¹、2⁻²、2⁻³……:

(0.101)₂
= 1×2⁻¹ + 0×2⁻² + 1×2⁻³
= 0.5 + 0 + 0.125
= (0.625)₁₀

8.2 十进制小数转二进制

采用“乘二取整,顺序排列”,每次保留小数部分继续乘二:

0.625 × 2 = 1.25 → 取 1,继续处理 0.25
0.25 × 2 = 0.5 → 取 0,继续处理 0.5
0.5 × 2 = 1.0 → 取 1,结束

(0.625)₁₀ = (0.101)₂

整数和小数部分分别转换后组合。例如 (45.625)₁₀ = (101101.101)₂。

8.3 为什么浮点数存在误差?

并非所有有限十进制小数都能写成有限二进制小数,例如十进制 0.1 的二进制展开会无限重复。常见浮点类型用有限位数存储,所以可能产生近似误差。

import math

print(0.1 + 0.2) # 0.30000000000000004
print((0.1 + 0.2) == 0.3) # False
print(math.isclose(0.1 + 0.2, 0.3)) # True

近似比较的容差应结合任务选择。Python 的 int() 用于解析整数文本,不会直接把 "101.101" 解析成二进制小数。

九、整数表示:无符号数、补码与溢出

9.1 同一串位可以有不同含义

11111111

按 8 位无符号整数解释时是 255;按 8 位有符号补码解释时是 -1。解释数据前要先知道位宽、类型和规则。

9.2 有符号补码范围

n 位有符号补码整数的范围为 -2^(n-1) 到 2^(n-1)-1。

位数 无符号范围 有符号补码范围
8 0~255 -128~127
16 0~65535 -32768~32767
32 0~4294967295 -2147483648~2147483647

9.3 负数补码示例

在 8 位前提下,求 -5 的补码:

+5:00000101
取反:11111010
加 1:11111011

所以 -5 的 8 位补码是 11111011。

也可以用 2⁸ - 5 = 251,再写成 8 位二进制。读取负数补码时,可将无符号值减去 2⁸,例如 251 - 256 = -5。

补码最高位可判断正负,但不能把剩余位直接当作负数的绝对值。

9.4 固定宽度与溢出

  11111111   (8 位无符号数 255)
+ 00000001
-----------
1 00000000 (数学结果 256,需要 9 位)

如果只保留低 8 位,结果是 00000000。真实语言和类型对溢出的处理不同,不能一律认为都会自动回绕;例如 C 的有符号整数溢出不能按普通回绕规则依赖。

Python 整数不使用固定 8 位或 32 位上限,会在内存允许范围内增长。需要模拟低 8 位时可以使用 value & 0xFF。

十、存储容量与数据速率换算

10.1 十进制单位

十进制前缀按 1000 逐级换算,千的规范符号为小写 k:

单位 字节数
1 kB 1000 B
1 MB 1000² B = 1000000 B
1 GB 1000³ B = 1000000000 B
1 TB 1000⁴ B

日常也常见 KB 写法,有些软件还用 KB、MB、GB 标注按 1024 换算的数值,因此需要确认实际约定。

10.2 二进制单位

二进制前缀按 1024 逐级换算:

单位 字节数
1 KiB 1024 B
1 MiB 1024² B = 1048576 B
1 GiB 1024³ B = 1073741824 B
1 TiB 1024⁴ B

为了避免歧义,本文用 kB、MB、GB 表示十进制,用 KiB、MiB、GiB 表示二进制。

10.3 换算示例

2048 B = 2 KiB
1536 KiB = 1.5 MiB
1 MiB = 1048576 B = 8388608 bit
1 GB ≈ 0.9313 GiB

标称 1 TB 的磁盘,按二进制换算约为 931.32 GiB,约为 0.9095 TiB。格式化、分区和系统预留等还可能进一步影响可用容量。

10.4 Mbps 与 MB/s

100 Mbps
= 100000000 bit/s
÷ 8
= 12500000 B/s
= 12.5 MB/s
≈ 11.92 MiB/s

这是按标称速率换算的数值。实际文件下载速度还受协议开销、服务器、网络质量和存储速度等影响。

以稳定 10 MB/s 下载 1 GB 数据,理想耗时:

1000 MB ÷ 10 MB/s = 100 s

换算前确认位、字节、十进制与二进制单位,不能只看“兆”这个口头说法。

十一、ASCII:字符与数值的对应

11.1 ASCII 是什么?

ASCII 定义了 128 个编码位置,用 7 位表示,范围为十进制 0~127,包括英文字母、数字字符、标点和控制字符。

在现代以 8 位字节存储 ASCII 文本的环境中,一个 ASCII 字符通常占 1 字节,最高位为 0。

11.2 常见字符

字符 十进制值 十六进制值 说明
NUL 0 00 空字符,不是可见数字 0
TAB 9 09 水平制表
LF 10 0A 换行控制字符
CR 13 0D 回车控制字符
空格 32 20 普通空格
0 48 30 数字字符 0
9 57 39 数字字符 9
A 65 41 大写 A
Z 90 5A 大写 Z
a 97 61 小写 a
z 122 7A 小写 z

数字 5 与字符 '5' 不同:前者是数值,后者在 ASCII 中对应数值 53,即十六进制 35。

11.3 控制字符与换行

Linux 文本常用 LF,Windows 文本常用 CRLF 作为行结束方式。两者占用的字节数可能不同,处理跨平台文本时要注意。

ASCII 不能表示汉字。“扩展 ASCII”没有唯一统一的 256 字符对应表,具体解释要看所用代码页或编码。

十二、Unicode 与 UTF 编码

12.1 字符、码点与字节

Unicode 为大量文字和符号规定码点,并定义相关文本处理规则。码点常写成 U+ 加十六进制数字。

字符 Unicode 码点 十进制值
A U+0041 65
中 U+4E2D 20013
😀 U+1F600 128512

码点是编号,编码形式规定如何把可编码的 Unicode 标量值变成代码单元序列,再以字节保存。Unicode 不等于“所有字符统一占两个字节”。

12.2 UTF-8、UTF-16 与 UTF-32

下表按一个 Unicode 标量值计算,不含 BOM 和文件格式额外内容:

编码 基本特点 A 中 😀
UTF-8 变长,ASCII 范围兼容 ASCII 1 B 3 B 4 B
UTF-16 使用一个或两个 16 位代码单元 2 B 2 B 4 B
UTF-32 一个 32 位代码单元 4 B 4 B 4 B

UTF-8 对 Unicode 标量值使用 1~4 字节;UTF-16 并不总是两个字节。UTF-16、UTF-32 保存为字节时还要处理字节序。

12.3 同一个“字符”可能有不同计数方式

视觉上的一个字符可能由多个码点组成,例如字母与组合重音,或一些表情序列。

Python 的 len(str) 通常统计码点数量,不是字节数,也不一定等于用户看到的字符数量。文件字节数则取决于编码、换行、BOM 等因素;Python 对象的内存占用还包含对象开销。

12.4 BOM 和其他编码

BOM 是某些 Unicode 文本开头使用的标记,可帮助识别字节序或编码。UTF-8 不需要通过 BOM 判断字节序,但文件仍可能带 UTF-8 BOM。

历史或特定场景还会遇到 GBK、GB18030 等编码。它们与 UTF-8 规则不同,读取时需要与文件实际编码一致。

十三、编码、解码与乱码

13.1 编码和解码的方向

字符文本 ——编码 encode——→ 字节
字节 ——解码 decode——→ 字符文本

Python 示例:

text = "A中😀"
data = text.encode("utf-8")

print(len(text)) # 3 个码点
print(len(data)) # 8 字节
print(data.hex(" ")) # 41 e4 b8 ad f0 9f 98 80
print(data.decode("utf-8"))

13.2 为什么会乱码?

写入和读取时使用不同规则,可能显示错误字符,也可能直接报解码错误。

data = "中".encode("utf-8")

print(data.decode("utf-8")) # 正确
print(data.decode("latin-1")) # 使用错误规则,得到错误文本

不是所有错误编码组合都会立刻报错,所以“程序没报错”不等于文本解码正确。

13.3 文件读写

from pathlib import Path

file_path = Path("encoding-practice.txt")
file_path.write_text("A中😀", encoding="utf-8")

print(file_path.read_text(encoding="utf-8"))
print(file_path.read_bytes().hex(" "))

这会创建或覆盖练习文件。遇到乱码时先确认原始编码、读取方式和显示环境;不要把忽略解码错误当成通用修复方法,否则可能丢失信息。

十四、位运算:按位与、或、异或、取反

位运算逐个处理整数二进制位。以下先用非负整数和固定 8 位示意图说明。

14.1 真值表

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

14.2 按位与 &

两位都为 1,结果才为 1:

  00001100   12
& 00001010 10
----------
00001000 8

常用于保留特定位或检查标志位。

14.3 按位或 |

至少一位为 1,结果为 1:

  00001100   12
| 00001010 10
----------
00001110 14

常用于将某些位置为 1。

14.4 按位异或 ^

两位不同为 1,相同为 0:

  00001100   12
^ 00001010 10
----------
00000110 6

常用于翻转指定位。Python 中 ^ 不是乘方,乘方使用 **。

14.5 按位取反 ~

固定 8 位示意:

原值:00001100
取反:11110011

Python 整数的位运算按具有无限符号扩展的补码模型理解,~x == -x - 1:

print(~12)          # -13
print((~12) & 0xFF) # 243,保留低 8 位

因此 ~12 不能直接解释成 8 位无符号数 243,必须明确位宽和掩码。

十五、移位、掩码与标志位

15.1 左移和右移

print(5 << 1)   # 10
print(5 << 2) # 20
print(20 >> 2) # 5

对 Python 的非负整数,左移 n 位等于乘 2^n,右移 n 位等于除以 2^n 后向下取整。

00000101 << 1 → 00001010
00010100 >> 2 → 00000101

Python 负整数右移会保留符号含义,例如 -3 >> 1 为 -2。固定宽度语言的移位还受类型和位数限制,不要直接套用所有 Python 规则。

15.2 位编号和掩码

最低有效位从 0 开始编号:

位编号:7 6 5 4 3 2 1 0
数值位:0 0 0 0 1 0 0 0

上面只有第 3 位为 1,对应 1 << 3,即十进制 8。掩码是一组用于选择或修改特定位的二进制位。

操作 Python 写法
检查第 k 位是否为 1 (value & (1 << k)) != 0
将第 k 位置 1 value | (1 << k)
将第 k 位清零 value & ~(1 << k)
翻转第 k 位 value ^ (1 << k)
取低 4 位 value & 0x0F
取第 4~7 位 (value >> 4) & 0x0F

15.3 用一字节保存多个状态

假设最低三位分别表示“就绪”“报警”“正在采集”:

READY = 1 << 0
ALARM = 1 << 1
RUNNING = 1 << 2

status = READY | RUNNING
print(f"{status:08b}") # 00000101
print(bool(status & READY)) # True
print(bool(status & ALARM)) # False

status |= ALARM # 设置报警位
status &= ~RUNNING # 清除采集位
status ^= READY # 翻转就绪位
print(f"{status:08b}") # 00000010

位运算 &、| 与逻辑运算 and、or 不同,判断表达式中建议用括号明确顺序。

十六、字节序与数据解释

16.1 一个数可以占多个字节

十六进制数 0x1234 需要两个字节表示,分别是 0x12 和 0x34。按内存地址从低到高排列:

字节序 字节排列
大端 Big-endian 12 34,高位字节在前
小端 Little-endian 34 12,低位字节在前

字节序讨论多字节值的字节排列,不是把每个字节内部的二进制数字倒过来。

16.2 Python 验证

value = 0x1234

print(value.to_bytes(2, byteorder="big").hex(" ")) # 12 34
print(value.to_bytes(2, byteorder="little").hex(" ")) # 34 12
print(int.from_bytes(bytes.fromhex("12 34"), byteorder="big")) # 4660

读取串口、网络协议、图像或二进制文件时,需要确认字段长度、字节序、有无符号和编码规则,不能只根据字节外观猜测内容。

例如文本 "12" 的 UTF-8 字节为 31 32,整数 12 按一个无符号字节存储时为 0C,含义相近但表示完全不同。

十七、使用 Python 验证进制与编码

17.1 整数转进制字符串

value = 45

print(bin(value)) # 0b101101
print(oct(value)) # 0o55
print(hex(value)) # 0x2d
print(format(value, "08b")) # 00101101
print(format(value, "02X")) # 2D

08b 表示二进制、至少宽 8 位、不足补零,不表示把整数限制为 8 位。值超过 255 时,仍会显示更多位。

17.2 进制字符串转整数

print(int("101101", 2))  # 45
print(int("55", 8)) # 45
print(int("45", 10)) # 45
print(int("2D", 16)) # 45
print(int("0x2D", 0)) # 45,按合法前缀识别

17.3 字符和码点转换

print(ord("A"))             # 65
print(ord("中")) # 20013
print(chr(65)) # A
print(f"U+{ord('中'):04X}") # U+4E2D

ord() 接受单个字符,返回码点;它的结果不是该字符的 UTF-8 字节。获取字节应使用 .encode("utf-8")。

十八、一个综合示例

下面模拟设备发送的数据包。协议是本教程自定义的练习格式,不对应具体设备。

18.1 数据格式

05 01 2C E4 B8 AD
字段 长度 约定
状态 1 B bit0 就绪、bit1 报警、bit2 正在采集,其余为 0
采样值 2 B 大端无符号整数,单位为 0.1 摄氏度
标签 剩余字节 UTF-8 文本

18.2 手工分析

  1. 状态 0x05 = 00000101₂,表示就绪、正在采集,没有报警。
  2. 采样值 0x012C = 1×256 + 44 = 300。
  3. 按约定缩放:300 × 0.1 = 30.0 摄氏度。
  4. 标签字节 E4 B8 AD 按 UTF-8 解码为“中”。
  5. 整个数据包长 6 B = 48 bit,不包含额外协议头和传输开销。

18.3 编程验证

将下面代码保存为 decode_packet.py:

packet = bytes.fromhex("05 01 2C E4 B8 AD")

status = packet[0]
raw_value = int.from_bytes(packet[1:3], byteorder="big", signed=False)
temperature = raw_value / 10
label = packet[3:].decode("utf-8")

print(f"状态:{status:08b}")
print("就绪:", bool(status & (1 << 0)))
print("报警:", bool(status & (1 << 1)))
print("采集中:", bool(status & (1 << 2)))
print("温度:", temperature)
print("标签:", label)
print("字节数:", len(packet))
print("位数:", len(packet) * 8)

运行:

python decode_packet.py

预期结果应与手算一致。该示例只处理已知合法样例,接收真实数据时还需校验长度、字段范围、文本编码及协议规定的校验信息。

十九、常见问题与易错点

问题 正确认识
内存与硬盘都是容量,是否能互换? 用途、访问方式和性能不同,不能直接等同
8 位有 256 种状态,最大值是否为 256? 无符号整数从 0 开始,最大值是 255
0x10 是否为十进制 10? 是十六进制 10,数值为十进制 16
十进制转整数进制,余数是否顺序读取? 应逆序读取;小数乘基取整才是顺序读取
1 KB 是否一定为 1024 B? 写法存在混用,先确认约定;KiB 明确为 1024 B
100 Mbps 是否等于 100 MB/s? 位与字节不同,标称换算为 12.5 MB/s
字符 0 是否等于 NUL? 字符 0 的 ASCII 值为 48,NUL 为 0
一个汉字是否固定占 2 B? 取决于编码和具体字符,UTF-8 常见汉字为 3 B
Unicode 是否等于 UTF-8? Unicode 定义字符码点等规则,UTF-8 是其编码形式之一
len(text) 是否为文本文件大小? 它通常计码点,编码后的字节数需单独计算
~12 是否就是 243? 在 Python 中是 -13,取低 8 位才得到 243
^ 是否表示乘方? Python 中表示按位异或,乘方是 **
格式化为 8 位是否会自动截断? 不会,显示宽度与存储位宽不同
相同字节是否一定代表相同数据? 还要知道类型、位宽、字节序和编码

二十、练习

建议先手算,再用程序验证,并写下换算过程。

20.1 计算机组成

  1. 分别说明 CPU、内存、SSD 的用途。
  2. 描述一个程序从文件到运行结果的简化过程。
  3. 说明为什么“内存 16 GB”和“磁盘 512 GB”不能当作同一指标相加。

20.2 进制转换

  1. 将 (110010)₂ 转成十进制、八进制、十六进制。
  2. 将 (125)₁₀ 转成二进制、八进制、十六进制。
  3. 将 (3A)₁₆ 转成二进制与十进制。
  4. 将 (237)₈ 转成二进制与十六进制。
  5. 将 (0.375)₁₀ 转成二进制小数。
  6. 判断 (102)₂、(89)₈、(1G)₁₆ 是否是合法表示,解释原因。

20.3 数值与容量

  1. 计算 12 位无符号整数的最大值。
  2. 写出 -6 的 8 位补码,并解释 11111010 的有符号值。
  3. 将 4096 B 换算为 KiB,将 2 MiB 换算为 B 和 bit。
  4. 分别计算 1 GB 和 1 GiB 的字节数,求两者之差。
  5. 按十进制单位,计算 200 Mbps 对应的 MB/s 理论数值。

20.4 编码与位运算

  1. 查询 B 和 b 的 ASCII 值及十六进制表示。
  2. 计算 "Hi中" 的码点数与 UTF-8 字节数。
  3. 判断“UTF-16 中每个字符一定为 2 B”是否正确。
  4. 计算 12 & 5、12 | 5、12 ^ 5、5 << 2、20 >> 1。
  5. 对 value = 0b10110010,提取低四位,将第 0 位置 1,将第 7 位清零。
  6. 将 0x1234 按小端写成两个字节,并说明用错误字节序读取会得到什么值。
  7. 修改综合示例,使报警位也为 1,检查其他字段是否保持不变。

20.5 部分参考答案

题目 参考结果
(110010)₂ 十进制 50,八进制 62,十六进制 32
(125)₁₀ 二进制 1111101,八进制 175,十六进制 7D
(3A)₁₆ 二进制 00111010,十进制 58
(237)₈ 二进制 10011111,十六进制 9F
(0.375)₁₀ (0.011)₂
12 位无符号最大值 4095
-6 的 8 位补码 11111010
4096 B 4 KiB
2 MiB 2097152 B,16777216 bit
1 GiB - 1 GB 73741824 B
200 Mbps 25 MB/s,未考虑实际开销
B、b 66 / 0x42;98 / 0x62
Hi中 3 个码点,5 个 UTF-8 字节
五个位运算题 4、13、9、20、10
10110010 的低四位 0010,即 2
将原值第 0 位置 1 10110011
将原值第 7 位清零 00110010
0x1234 小端字节 34 12,若误按大端读取得到 0x3412,即 13330
数据包增加报警位 状态从 05 改为 07

二十一、常用知识速查表

知识点 规则或示例
1 字节 本教程按 8 bit
n 位组合数 2^n
n 位无符号范围 0~2^n-1
n 位有符号补码范围 -2^(n-1)~2^(n-1)-1
其他进制转十进制 按位权展开求和
十进制整数转 r 进制 除 r 取余,逆序排列
十进制小数转二进制 乘 2 取整,顺序排列
二进制与八进制 每 3 位一组
二进制与十六进制 每 4 位一组
1 MB / 1 MiB 1000000 B / 1048576 B
bit/s 转 B/s 数值除以 8
ASCII 7 位,128 个编码位置
UTF-8 每个 Unicode 标量值使用 1~4 B
编码 / 解码 文本到字节 / 字节到文本
按位与 / 或 / 异或 / 取反 & / `
保留低 8 位 value & 0xFF
左移 / 右移 << / >>
Python 整数转进制字符串 bin()、oct()、hex()
进制字符串转整数 int(text, base)
字符与码点 ord()、chr()
大端 / 小端 高位字节在前 / 低位字节在前

二十二、相关学习资料

← 继续探索学习路径反馈问题 ↗