数值计算的艺术
计算机只有有限精度,把纸上的数学公式照搬进去,常常算出垃圾。这个专栏从「误差」这个主角讲起,一路到求根、线性方程、插值、积分、微分方程、FFT、蒙特卡洛与最优化——代码优先,用 NumPy 手写核心算法,把「怎么算得又快又对」这门手艺讲透。
序 · 为什么「算得快」不等于「算得对」
先看一行会让人愣住的代码:
>>> 0.1 + 0.2 == 0.3
False
>>> 0.1 + 0.2
0.30000000000000004这不是 Python 的 bug,而是几乎所有编程语言、所有用浮点数的计算机共有的现实。它揭示了一件容易被忽略的事:计算机做的不是纸上那种精确的实数运算,而是一种有限精度的近似。 一旦你把课本上那些完美的数学公式,原封不动地搬进计算机,它随时可能给你一个看起来对、其实错得离谱的答案。
数值计算(numerical computing),就是研究怎么在这台「不精确」的机器上,算出足够可信的结果——这是一门手艺,也是这个专栏标题里「艺术」二字的由来。
这门手艺的主角:误差
如果说别的编程课的主角是「算法」,那这门课的主角是「误差」。 同一个数学问题,能算对还是算崩,往往不取决于你用了多聪明的公式,而取决于四个词:舍入误差(每步运算都在丢位)、灾难性抵消(两个相近的数一减就出事)、条件数(问题本身对误差有多敏感)、稳定性(算法会不会把小误差滚成大错)。
所以本专栏第一站,专门用四章把「误差」这个主角立起来;之后每一个方法——求根、解方程、积分、微分方程——我们都会放在同一把尺子下问:它会不会放大误差?稳不稳?收不收敛? 这条主线贯穿始终,是「会调 API」和「懂数值计算」的分水岭。
这个专栏怎么讲
代码优先,手写 + 库对照。 我们用 Python + NumPy(理论对照 SciPy)。每个核心算法都会从零手写一遍——因为数值计算的精髓在于「知道它内部怎么运作、会在哪出错」,光会 scipy.optimize 是不够的;写完再给出库的用法,让你既懂原理、又能实战。
用「收敛表」代替空谈。 数值方法好不好,看它收敛多快、误差多小。我们会反复打印「第几步 → 当前误差」这样的表格,让你亲眼看着误差怎么一步步缩小(或者失控发散)——数字不会骗人。
路线图
分七站,从「机器怎么算数」一路铺到高级利器:
第一站 · 有限精度的世界 —— 浮点数原理、机器精度、灾难性抵消、条件数与稳定性。把误差这个主角讲透,打牢地基。
第二站 · 求根 —— 解 :二分法(最稳)、牛顿法(最快但会翻车)、割线法与收敛阶。
第三站 · 线性代数 —— 解 :高斯消元与 LU 分解、选主元与病态矩阵、迭代法(对付大稀疏)、以及特征值。
第四站 · 逼近 —— 插值与拟合:多项式插值的 Runge 陷阱、样条的智慧、最小二乘。
第五站 · 微积分的数值版 —— 数值微分(为什么天生不稳)、数值积分、常微分方程(Euler 到 RK4)、刚性方程。
第六站 · 更多利器 —— 快速傅里叶变换(FFT)、蒙特卡洛(用随机算积分)、最优化(梯度下降与牛顿法找极值)。
第七站 · 收尾 —— 数值计算的十条铁律 + 「何时用库、何时手写」+ 常见陷阱清单。
读之前,你最好有
- 会 Python:函数、循环、
numpy数组切片,够了。 - 高数 / 线代的基本概念:导数是斜率、积分是面积、矩阵怎么乘——有「感觉」就行,细节需要时就地补一小段。
- 一点「较真」的劲头:这门课会反复问「这个答案到底准不准、误差多大、可信吗」。在数值计算里,「差不多对」和「真的对」之间,隔着一整门学问。
准备好了,我们从那行 0.1 + 0.2 背后的真相开始——计算机到底怎么存一个实数:浮点数:0.1 + 0.2 为什么不等于 0.3。