SICI · 天机门 · 第十一章

数字运算的精密之道 · 筑基五层

你以为算术就是1+1=2。但0.1+0.2在计算机里不等于0.3。这不是bug——这是有限位表示无限的代价。

门楣刻字:「你以为0.1+0.2=0.3。记下了。」
序章

算经阁

0.1 + 0.2 等于几?

算经阁的门没有锁,只有一道刻痕——上面写着「算」字,笔画被人用指甲刮出了一道额外的裂痕。

中断之刃,中断处理机制

诺依曼老祖站在门前,手边悬着一枚算珠,珠面上刻满了 0 和 1。

诺依曼老祖 诺依曼老祖

「你学过加法器。半加器、全加器、行波进位——ch02 的东西。但你可知,三十二位的进位要传多久?0.1+0.2 又等于几?」

精度之蚀 精度之蚀

「你以为0.1+0.2=0.3。记下了。」

0.1 + 0.2 浮点精度预测挑战器

先下注,再探索 ALU 全貌。算珠在你手里微微发烫。

先回答:0.1 + 0.2 等于几?
第一幕 · 自信

进位阵 · 延迟之墙

加法不是瞬时的——进位要一级一级传过去

石径尽头是一面墙——墙上刻着三十二个格子,每个格子里坐着一个全加器,首尾相连。墙的底部有一只钟,钟面上没有数字,只有一圈刻度。

诺依曼老祖 诺依曼老祖

「ch02 的行波进位加法器。三十二位,进位从最低位传到最高位,要穿过三十一级门。你猜,要多久?」

精度之蚀 精度之蚀

「你以为加法是瞬时的。等你看见钟面,就知道你等的不是加法,是进位。」

进位链延迟曲线追踪器

切换加法器模式 → 测量门延迟 → 对比硬件代价

门延迟:

三种加法器延迟-面积对比

第一幕 · 自信

补码殿 · 加减归一

一座加法器搞定加减——补码把减法翻译成加法

殿中央悬着一台加法器。老祖在加法器旁边放了一面镜子。镜子里是同样的加法器,但输入端的 B 被取了反。

诺依曼老祖 诺依曼老祖

「减法 A−B。你打算怎么算?提醒你——计算机里只有加法器。没有减法器。」

补码加减统一电路 · Sub 信号 + XOR 门 + C₀

切换 Sub 信号 → 观察 XOR 取反与 C₀ 进位 → 验证加减归一

Sub 信号:
C₀ 进位输入: 0
结果:—
溢出检测 V = C₃₁ ⊕ C₃₂: V = 0
第一幕 · 崩塌

乘除塔 · 整数之限

七层算法全通,却连 0.1 都输不进去

乘除塔是一座七层石塔。每一层都刻着一种算法。你抬头看塔顶——那里有一扇门,门上刻着一个问题:「1 ÷ 3 = ?」

诺依曼老祖 诺依曼老祖

「七层你全爬完,算术的整数侧就通了。」

精度之蚀 精度之蚀

「你走完了整数的全部七层。加法、减法、乘法、除法——全通了。但你连 0.1 都输不进去。」

整数乘除算法四选一推演器

依次点亮七层算法 → 推开门 → 撞上整数之限

第二幕 · 挣扎

浮点台 · IEEE 之镜

有限位制造一套自洽的数系——三个区间各有使命

裂缝的另一侧是一面巨大的镜台。镜面上刻着三十二个格子——1 个符号位、8 个指数位、23 个尾数位。

诺依曼老祖 诺依曼老祖

「IEEE 754 单精度。你在 S0 猜错过 0.1+0.2 的地方——答案就刻在这面镜子上。先学怎么把一个实数装进这 32 个格子。」

IEEE 754 编码拆解 · 三区间探索

选择实数 → 逐位编码 → 探索三个区间 → 单双精度对比

第二幕 · 挣扎

对阶殿 · 消失的尾数

对阶是凶手——移出去的位永远消失了

殿中央悬着两根光柱——一根刻着 1.0×2⁰,一根刻着 1.0×2⁻²³。你想:1.0 + 0.000000119... ≈ 1.0。很合理。

诺依曼老祖 诺依曼老祖

「不是『大约等于』。是『在 23 位尾数里,1.0×2⁻²³ 加上去之后,尾数最低位翻了吗?』把它们加起来。」

浮点加法四步 · 对阶 → 相加 → 规格化 → 舍入

拖动 B 尾数右移对阶 → 相加 → 选择舍入模式 → 观察 B 是否存活

A = 1.00000000000000000000000 × 2⁰
B = 1.00000000000000000000000 × 2⁻²³(对阶后)
第二幕 · 再崩塌

舍入狱 · 误差雪崩

浮点不是实数的近似——它是另一套代数法则

舍入狱是一座环形石牢。牢中央悬着一只算盘——上面跑着一段循环:sum = 0; for (i = 0; i < 10000; i++) sum += 0.1;

精度之蚀 精度之蚀

「理论上 sum 应该等于 1000。你猜,实际上等于几?误差不会累积的——对吧?」

诺依曼老祖 诺依曼老祖

「你学的实数代数——结合律、分配律——在它的世界里全是废纸。」

浮点误差雪崩曲线追踪器

运行 10000 次累加 → 切换舍入模式 → 灾难性抵消 → 结合律违反

sum = 0; for (i = 0; i < 10000; i++) sum += 0.1;
灾难性抵消:1 − (1 − 10⁻⁸) = ?
结合律违反:a=10³⁰, b=−10³⁰, c=10⁻³⁰
第三幕 · 顿悟前兆

融乘阁 · FMA 之光

两次舍入变成一次——精度最坏减半

融乘阁里只有一台法器——三个输入端口 A、B、C,一个输出端口。

诺依曼老祖 诺依曼老祖

「浮点乘法你已经会了,浮点加法你也会了。那 A×B+C 呢?两次运算——两次舍入。如果我只舍入一次呢?」

FMA 对比 · 先乘后加(两次舍入) vs FMA(一次舍入)

切换模式 → 观察 48 位乘积是否截断 → 对比灾难性抵消案例

灾难性抵消案例:A=1.0, B=1+2⁻²⁴, C=−1.0
第三幕 · 抉择

权衡殿 · 三角之秤

面积、速度、精度——三角上没有免费的午餐

权衡殿中央悬着一架三角天平——三个顶点标着「面积」「速度」「精度」。天平下面散落着你这一路见过的所有模块。

诺依曼老祖 诺依曼老祖

「一颗芯片的面积是有限的。你要在有限面积里装下你的 ALU。每一个模块都要付面积的税。选吧。」

精度之蚀 精度之蚀

「你想要精度?付面积。你想要速度?付面积。你以为精度可以无代价提升?」

三角天平 · 三场景 ALU 配置器

为嵌入式 / 桌面 CPU / AI 加速器各配置 ALU → 观察三角权衡

第三幕 · 最高潮

Boss 战 · 精度之蚀

三问清算 · 排除法收网

权衡殿的灯火齐灭。裂缝从四面八方压过来,凝成一个由无数个 0 和 1 溶解又重组的身影——没有面孔,只有一道不断侵蚀的裂痕。它手中悬着一本账簿,封面刻着四个字:精度账本。

精度之蚀 精度之蚀

「你在算经阁里走了十层。每一层,你都在低估我。现在,回答我三个问题。答错,从 S3 重走。但你的刻痕不会消失——它们是你的弹药。」

渊账累计 0 笔 · 三问全对后清零

第三幕 · 收束

尾声 · 十进制之钥

BCD 让 0.1+0.2=0.3——但代价是效率

精度之蚀消散时,算经阁的灯一盏盏亮回来。诺依曼老祖走过来,手里多了一枚铜钥匙——钥匙上刻着十个凹槽,每个凹槽里是一个 0 到 9 的数字。

诺依曼老祖 诺依曼老祖

「银行算利息,0.1 元 + 0.2 元必须等于 0.3 元——不是 0.30000000000000004。一次都不行。怎么办?」

诺依曼老祖 诺依曼老祖

「你这一章设计的加法器、乘法器、FMA 单元——它们每一个都需要好几个周期才能算完。但现代处理器每个时钟周期都在执行指令。怎么做到的?那叫流水线。下一章的题。」

BCD 编码 · 加法修正 · 全章知识图谱

编码 0.1 → BCD → 0.1+0.2=0.3 精确 → 5+8 修正 → 图谱点亮

BCD 加法:5 + 8 = ?