# 数值计算的艺术

> 计算机只有有限精度，把纸上的数学公式照搬进去，常常算出垃圾。这个专栏从「误差」这个主角讲起，一路到求根、线性方程、插值、积分、微分方程、FFT、蒙特卡洛与最优化——代码优先，用 NumPy 手写核心算法，把「怎么算得又快又对」这门手艺讲透。

- 作者：David（道雾轩）
- 最后更新：2026-08-03
- 原文：https://daiw.org/manual/numerical-computing
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# 序 · 为什么「算得快」不等于「算得对」

先看一行会让人愣住的代码：

```python
>>> 0.1 + 0.2 == 0.3
False
>>> 0.1 + 0.2
0.30000000000000004
```

这不是 Python 的 bug，而是**几乎所有编程语言、所有用浮点数的计算机**共有的现实。它揭示了一件容易被忽略的事：**计算机做的不是纸上那种精确的实数运算，而是一种有限精度的近似。** 一旦你把课本上那些完美的数学公式，原封不动地搬进计算机，它随时可能给你一个**看起来对、其实错得离谱**的答案。

数值计算（numerical computing），就是研究**怎么在这台「不精确」的机器上，算出足够可信的结果**——这是一门手艺，也是这个专栏标题里「艺术」二字的由来。

## 这门手艺的主角：误差

<Callout type="info">
  **如果说别的编程课的主角是「算法」，那这门课的主角是「误差」。** 同一个数学问题，能算对还是算崩，往往不取决于你用了多聪明的公式，而取决于四个词：**舍入误差**（每步运算都在丢位）、**灾难性抵消**（两个相近的数一减就出事）、**条件数**（问题本身对误差有多敏感）、**稳定性**（算法会不会把小误差滚成大错）。

  所以本专栏第一站，专门用四章把「误差」这个主角立起来；之后**每一个方法**——求根、解方程、积分、微分方程——我们都会放在同一把尺子下问：**它会不会放大误差？稳不稳？收不收敛？** 这条主线贯穿始终，是「会调 API」和「懂数值计算」的分水岭。
</Callout>

## 这个专栏怎么讲

**代码优先，手写 + 库对照。** 我们用 **Python + NumPy**（理论对照 SciPy）。每个核心算法都会**从零手写一遍**——因为数值计算的精髓在于「知道它内部怎么运作、会在哪出错」，光会 `scipy.optimize` 是不够的；写完再给出库的用法，让你既懂原理、又能实战。

**用「收敛表」代替空谈。** 数值方法好不好，看它**收敛多快、误差多小**。我们会反复打印「第几步 → 当前误差」这样的表格，让你**亲眼看着**误差怎么一步步缩小（或者失控发散）——数字不会骗人。

## 路线图

分七站，从「机器怎么算数」一路铺到高级利器：

**第一站 · 有限精度的世界** —— 浮点数原理、机器精度、灾难性抵消、条件数与稳定性。把误差这个主角讲透，打牢地基。

**第二站 · 求根** —— 解 $f(x)=0$：二分法（最稳）、牛顿法（最快但会翻车）、割线法与收敛阶。

**第三站 · 线性代数** —— 解 $Ax=b$：高斯消元与 LU 分解、选主元与病态矩阵、迭代法（对付大稀疏）、以及特征值。

**第四站 · 逼近** —— 插值与拟合：多项式插值的 Runge 陷阱、样条的智慧、最小二乘。

**第五站 · 微积分的数值版** —— 数值微分（为什么天生不稳）、数值积分、常微分方程（Euler 到 RK4）、刚性方程。

**第六站 · 更多利器** —— 快速傅里叶变换（FFT）、蒙特卡洛（用随机算积分）、最优化（梯度下降与牛顿法找极值）。

**第七站 · 收尾** —— 数值计算的十条铁律 + 「何时用库、何时手写」+ 常见陷阱清单。

## 读之前，你最好有

- **会 Python**：函数、循环、`numpy` 数组切片，够了。
- **高数 / 线代的基本概念**：导数是斜率、积分是面积、矩阵怎么乘——有「感觉」就行，细节需要时就地补一小段。
- **一点「较真」的劲头**：这门课会反复问「这个答案到底准不准、误差多大、可信吗」。**在数值计算里，「差不多对」和「真的对」之间，隔着一整门学问。**

准备好了，我们从那行 `0.1 + 0.2` 背后的真相开始——**计算机到底怎么存一个实数**：[浮点数：0.1 + 0.2 为什么不等于 0.3](https://daiw.org/manual/numerical-computing/floating-point)。

## 本专栏篇目

- [数值计算的艺术](https://daiw.org/manual/numerical-computing.md): 计算机只有有限精度，把纸上的数学公式照搬进去，常常算出垃圾。这个专栏从「误差」这个主角讲起，一路到求根、线性方程、插值、积分、微分方程、FFT、蒙特卡洛与最优化——代码优先，用 NumPy 手写核心算法，把「怎么算得又快又对」这门手艺讲透。

### 有限精度的世界 · 地基

- [浮点数 · 0.1 + 0.2 为什么不等于 0.3](https://daiw.org/manual/numerical-computing/floating-point.md): 计算机用浮点数近似实数——本质是二进制的科学计数法。这一章讲清 IEEE 754 的结构、为什么 0.1 根本存不准、由此引出的第一条铁律：浮点数永远别用 == 比较，要用容差。
- [机器精度 · 误差有多大，以及怎么压住它](https://daiw.org/manual/numerical-computing/machine-epsilon.md): 「存不准」到底不准多少？机器精度 ε 给出了精确标尺——单次运算的相对误差不超过它。这一章量化 float64 的精度（约 16 位有效数字），看误差在长累加里怎么滚大，并用 Kahan 补偿求和把它压住。
- [灾难性抵消 · 两个相近的数相减](https://daiw.org/manual/numerical-computing/cancellation.md): 累积误差是慢性病，灾难性抵消是急性发作：两个相近的数一相减，有效数字当场湮灭，相对误差瞬间放大千万倍。这一章用求根公式的经典翻车现场演示它，并教你怎么重排公式把它绕开。
- [条件数与稳定性 · 是问题病态，还是算法不稳](https://daiw.org/manual/numerical-computing/conditioning.md): 误差放大有两种：一种是算法写得不好（可以换算法救），一种是问题本身对误差敏感（再好的算法也救不了）。区分它们靠两个词——稳定性（算法的属性）和条件数（问题的属性）。这一章讲清，并教你算出「这个结果还能信几位」。

### 求根 · 解 f(x)=0

- [二分法 · 最笨，但绝不失手](https://daiw.org/manual/numerical-computing/bisection.md): 解 f（x）=0 的第一个方法：二分法。只要你能给出一个「一正一负」的区间把根夹住，它就保证收敛——每步把区间对半砍。这一章手写它、打印收敛表，并讲清它的取舍：极其可靠，但慢（线性收敛）。
- [牛顿法 · 切线的力量，与它翻车的时候](https://daiw.org/manual/numerical-computing/newton.md): 牛顿法顺着切线滑向根，每步让正确位数翻倍——二次收敛，快得惊人。这一章手写它、打印「位数翻倍」的收敛表，也诚实展示它翻车的三种方式：导数为零、跑飞、来回震荡。快与险，是它的一体两面。
- [不动点与割线法 · 收敛阶怎么量](https://daiw.org/manual/numerical-computing/iteration-order.md): 二分是「线性」、牛顿是「二次」——这个「收敛阶」到底怎么定义、怎么测？这一章讲透不动点迭代（以及它收敛的条件）、免导数却快过二分的割线法（收敛阶是黄金比 1.618），并给一张求根方法的取舍总表。

### 线性代数 · 解 Ax=b

- [高斯消元与 LU 分解 · 解方程组的主力](https://daiw.org/manual/numerical-computing/gaussian-lu.md): 解 Ax=b 是数值计算里最基础、也最庞大的一块。这一章从人人学过的高斯消元讲起，引出 LU 分解——把矩阵拆成 L·U，一次分解、多次复用，还点破一条铁律：解方程组千万别求逆矩阵。
- [选主元与病态矩阵 · 方程为什么会算崩](https://daiw.org/manual/numerical-computing/pivoting.md): 高斯消元里「除以主元」是个定时炸弹：主元为 0 直接崩，主元很小则误差被放大。解药是「选主元」——每步把最大的元素换到对角线上。这一章演示不选主元怎么算出错误解，并厘清「算法不稳」和「矩阵病态」两种崩法。
- [迭代法 · Jacobi、Gauss-Seidel 与共轭梯度](https://daiw.org/manual/numerical-computing/iterative-linear.md): 几百万维的大稀疏方程组，直接法 O(n³) 跑不动。迭代法从一个猜测出发、反复逼近解，每步只做便宜的矩阵向量乘。这一章手写 Jacobi 与 Gauss-Seidel，讲清收敛条件，并介绍对称正定系统的王牌——共轭梯度。
- [特征值 · 幂迭代与 QR 算法](https://daiw.org/manual/numerical-computing/eigenvalues.md): 特征值 Av=λv 在 PCA、PageRank、稳定性分析里无处不在。这一章手写幂迭代（反复乘 A 就能揪出最大特征值），介绍所有库都在用的 QR 算法，并点破一个反直觉的铁律：千万别用特征多项式求根来算特征值。

### 逼近 · 插值与拟合

- [多项式插值与 Runge 现象 · 高次不是越准](https://daiw.org/manual/numerical-computing/interpolation.md): 给一堆点，穿过它们的多项式唯一存在。但一个惊人的反直觉：在等距点上用高次多项式插值，边缘会剧烈震荡，点越多越糟——这就是 Runge 现象。这一章用代码复现它，并给出两条解药。
- [样条与最小二乘 · 分段的智慧与超定拟合](https://daiw.org/manual/numerical-computing/splines-lsq.md): 样条用一段段低次多项式拼接，天然免疫 Runge 现象，是插值主力。而当数据带噪声，你压根不该穿过每个点——那是在拟合噪声，该用最小二乘去「近似」。这一章讲清这两件事，以及「插值 vs 拟合」的根本区别。

### 微积分的数值版

- [数值微分 · 有限差分，以及它为什么不稳](https://daiw.org/manual/numerical-computing/differentiation.md): 用函数值近似导数，靠有限差分。但它藏着一个尴尬的矛盾：步长 h 越小，截断误差越小，可 h 太小又会引发灾难性抵消——存在一个最优 h，再小反而更差。这一章用「U 形误差曲线」把这个「天生不稳」讲透。
- [数值积分 · 梯形、Simpson 与自适应](https://daiw.org/manual/numerical-computing/integration.md): 数值积分和数值微分恰好相反——它又稳又好算（积分抹平误差，微分放大误差）。这一章从梯形法讲到 Simpson（精度从 O(h²) 跳到 O(h⁴)）、自适应积分和高斯求积，并说清为什么 scipy.integrate.quad 是你日常的默认选择。
- [常微分方程 · 从 Euler 到 RK4](https://daiw.org/manual/numerical-computing/ode-euler-rk.md): 已知变化率 y'=f（t，y），求 y 随时间怎么演化——这是数值计算里极重要的一大类问题。这一章从最简单的 Euler 法（沿切线走一步）讲到主力 RK4（每步探四个斜率），用代码对比精度，并给出实践默认 solve_ivp。
- [刚性与隐式方法 · 显式为什么会爆炸](https://daiw.org/manual/numerical-computing/stiffness.md): 有些 ODE「快慢尺度悬殊」，叫刚性方程。对它，RK4 这类显式方法会被迫用小到离谱的步长——不是为了精度，是为了不爆炸。这一章用 y'=-1000y 演示显式发散，再用隐式方法（每步解个方程）取回任意大步长的稳定。

### 更多利器 · 变换、随机与最优化

- [快速傅里叶变换 · 从 O(n²) 到 O(n log n)](https://daiw.org/manual/numerical-computing/fft.md): FFT 被誉为 20 世纪最重要的算法之一。它把离散傅里叶变换从 O(n²) 加速到 O(n log n)，让信号处理、音频、图像压缩、频谱方法全都成为可能。这一章讲清 DFT 在做什么、FFT 快在哪，并用代码从一段带噪信号里「捞」出隐藏的频率。
- [蒙特卡洛 · 用随机性做计算](https://daiw.org/manual/numerical-computing/monte-carlo.md): 当维度太高、区域太复杂，确定性方法全线崩溃时，故意「掷骰子」反而能算。这一章从「扔飞镖估 π」讲清蒙特卡洛的原理，说明它 1/√N 的慢收敛为什么在高维里反而无敌（维度灾难），以及它在金融、物理、渲染里的地位。
- [最优化 · 梯度下降与找到最小值](https://daiw.org/manual/numerical-computing/optimization.md): 「找到让函数最小的那个点」渗透进一切现代应用——机器学习训练、曲线拟合、工程设计，本质都是最优化。这一章从梯度下降（沿负梯度下山）讲起，说清学习率的两难、凸与非凸的分野，以及为什么实践里直接用 scipy.optimize.minimize。

### 收尾

- [收尾 · 一张图串起整条主线](https://daiw.org/manual/numerical-computing/recap.md): 七站走完，回头看。这一章不引入新知识，而是把整条专栏里反复出现的几条主线——误差是主角、病态与不稳、灾难性抵消、数学等价≠数值等价、步长两难、直接法vs迭代法——收拢成一张全景图和一套世界观。
