# 蒙特卡洛 · 用随机性做计算

> 当维度太高、区域太复杂，确定性方法全线崩溃时，故意「掷骰子」反而能算。这一章从「扔飞镖估 π」讲清蒙特卡洛的原理，说明它 1/√N 的慢收敛为什么在高维里反而无敌（维度灾难），以及它在金融、物理、渲染里的地位。

- 作者：David（道雾轩）
- 专栏：数值计算的艺术（https://daiw.org/manual/numerical-computing.md）
- 最后更新：2026-07-14
- 原文：https://daiw.org/manual/numerical-computing/monte-carlo
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# 蒙特卡洛 · 用随机性做计算

第二件利器反直觉：**故意引入随机性来做确定的计算**。这就是**蒙特卡洛方法**——名字来自摩纳哥的赌场。听起来像玄学，却是金融、物理、图形学、统计里最重要的工具之一。

## 扔飞镖估 π

先看最经典的例子：**怎么用随机数估计 $\pi$？** 往一个 $1\times1$ 的正方形里随机扔飞镖，数一数**落在 $\frac14$ 圆内**（到原点距离 $\le 1$）的比例。因为这个 $\frac14$ 圆面积是 $\pi/4$，落入比例应当趋近 $\pi/4$，于是：

$$
\pi \approx 4 \times \frac{\text{落在圆内的点数}}{\text{总点数}}
$$

```python
import numpy as np

rng = np.random.default_rng(0)
n = 1_000_000
x, y = rng.random(n), rng.random(n)          # 均匀撒 100 万个点
inside = (x**2 + y**2 <= 1).sum()            # 落在 1/4 圆内的
print(4 * inside / n)                         # 3.141708  ≈ π
```

没有解析几何、没有积分公式，**纯靠随机撒点数比例**，就把 $\pi$ 估到了小数点后两三位。这就是蒙特卡洛的精髓：**把「算一个量」转化为「对随机样本求平均」。**

## 慢收敛：误差只按 1/√N 降

蒙特卡洛有个绕不开的软肋——**收敛慢**。它的误差按 $1/\sqrt{N}$ 下降：

$$
\text{误差} \sim \frac{1}{\sqrt{N}}
$$

<Callout type="warn">
  **$1/\sqrt{N}$ 意味着：精度每提高 10 倍，样本量得增加 100 倍。** 想从 2 位有效数字到 3 位，样本要涨 100 倍；这在低维问题上，远远打不过[前面](https://daiw.org/manual/numerical-computing/integration)梯形、Simpson 那种 $O(h^2)$、$O(h^4)$ 的确定性方法。所以**一维、二维的积分，别用蒙特卡洛**——它慢且糙。那它的价值在哪？答案藏在「维度」这个词里。
</Callout>

## 杀手锏：高维，维度灾难

蒙特卡洛真正无可替代的地方，是**高维**。它 $1/\sqrt{N}$ 的收敛率有个惊人的性质：**与维度无关**。

而确定性的网格方法恰恰栽在维度上。想在 $D$ 维空间上用网格积分，每维取 10 个点，总点数是 $10^D$——**$D=10$ 就要 $10^{10}$ 个点，$D=20$ 直接 $10^{20}$，彻底算不动。** 这就是著名的**维度灾难（curse of dimensionality）**。

<Callout type="info">
  **蒙特卡洛的收敛率 $1/\sqrt{N}$ 完全不看维度** ——不管是 3 维还是 300 维，同样数量的样本给出同样量级的误差。于是在高维里，格局彻底反转：网格法指数级爆炸、根本不可行，而蒙特卡洛稳稳地照跑不误。**「低维用确定性方法，高维用蒙特卡洛」** 就是这么来的。这也是为什么：

  - **金融**：期权定价常涉及几十上百个标的 / 时间步的高维积分 → 蒙特卡洛。
  - **物理**：统计力学、粒子输运的高维相空间积分 → 蒙特卡洛。
  - **贝叶斯统计**：高维后验分布采样 → 马尔可夫链蒙特卡洛（MCMC）。
  - **图形学**：光线追踪对光路空间积分（路径追踪）→ 蒙特卡洛渲染。
</Callout>

## 一个更实用的形态：蒙特卡洛积分

把估 $\pi$ 的思路一般化，就是**蒙特卡洛积分**：要算 $\int_\Omega f\,dx$，就在区域里均匀采 $N$ 个点，用**样本均值 × 区域体积**来估：

```python
# 估计 ∫₀¹∫₀¹ e^{-(x²+y²)} dx dy
rng = np.random.default_rng(1)
n = 1_000_000
x, y = rng.random(n), rng.random(n)
vals = np.exp(-(x**2 + y**2))
print(vals.mean())            # ≈ 0.5577  (区域体积为 1,直接就是均值)
```

区域再怪、维度再高，只要能**采样**、能**求值**，蒙特卡洛就能给出估计——这种「不挑形状、不惧维度」的普适性，是它的立身之本。

## 小结与下一章

**蒙特卡洛**用随机采样做计算（扔飞镖估 $\pi$ 是原型），核心是「把求一个量转成对随机样本求平均」。它误差按 $1/\sqrt{N}$ 慢收敛，**低维打不过确定性方法**；但收敛率**与维度无关**，于是在高维里反杀网格法的**维度灾难**，成为金融、物理、贝叶斯、渲染的支柱。

第三件、也是最后一件利器，是几乎渗透进一切现代应用（尤其机器学习）的**最优化**——怎么找到让一个函数最小的那个点。👉 [最优化：梯度下降与找到最小值](https://daiw.org/manual/numerical-computing/optimization)。

## 参考文献

- [1] Metropolis & Ulam.「The Monte Carlo Method.」1949. —— 蒙特卡洛开山之作。
- [2] Robert & Casella.《Monte Carlo Statistical Methods》—— MCMC 与统计采样。
- [3] Pharr, Jakob & Humphreys.《Physically Based Rendering》—— 蒙特卡洛渲染。
