3. 随机数生成基础与正态分布采样

布朗运动的数值模拟,本质上是在计算机里“制造”一条随机游走路径。而这条路径的每一步增量,都来自随机数。因此,能否得到统计性质正确的随机数,直接决定了模拟结果是否可信。本节从伪随机数生成器(PRNG)的原理出发,讲清楚如何把均匀随机数转换为标准正态分布样本,并用可观察的统计量验证采样质量。

伪随机数生成器:确定性的“假随机”

计算机无法产生真正的随机数,只能通过确定性算法生成看似随机的序列,称为伪随机数。最经典的是线性同余生成器(LCG),其递推式为:

x_{n+1} = (a * x_n + c) mod m
u_n = x_n / m

其中 x_0 为种子,a、c、m 为参数,u_n 落在 [0,1) 区间。给定相同的种子,序列完全可复现——这既是优点(实验可重复),也是缺点(并非真随机)。LCG 的周期最多为 m,且低位比特随机性差,因此现代实践通常不直接手写 LCG,而是使用语言标准库中更高质量的生成器,例如 Python 的 numpy.random.default_rng()(基于 PCG64)、C++ 的 std::mt19937(梅森旋转)。

使用 PRNG 有三条基本纪律:第一,显式指定种子,保证结果可复现;第二,不要用时间戳反复重置种子,否则会破坏序列的统计独立性;第三,不要把同一个生成器实例在并行任务中共享,应为每个线程或进程分配独立的种子流(如 SeedSequence 派生)。

从均匀分布到标准正态分布

PRNG 输出的是 [0,1) 上的均匀分布,而布朗运动增量需要 N(0,1) 样本。转换方法主要有三种:

  • Box-Muller 变换:取两个独立均匀数 u1, u2,令 z1 = sqrt(-2 ln u1) cos(2π u2),z2 = sqrt(-2 ln u1) sin(2π u2),一次得到两个独立标准正态样本。原理清晰,但涉及对数、三角函数,速度一般。
  • 逆变换法:计算 z = Φ^{-1}(u),其中 Φ^{-1} 是标准正态分布函数的反函数。概念直接,但需要高精度反函数实现。
  • Ziggurat 算法:用分层拒绝采样快速生成正态样本,是现代库的常用方案,速度快且精度高。

实际工程中,直接调用 rng.standard_normal(size) 即可,无需手写变换。但理解 Box-Muller 有助于明白:正态样本的“随机性来源”仍是均匀随机数,若底层均匀数有偏,正态样本也会失真。

统计特性验证:不能只看均值

采样完成后必须验证。仅检查均值接近 0 是不够的,还要看方差、偏度、峰度以及分布形状。下面给出一个可直接运行的验证示例(参数与结果为教学示例设定,非实测数据):

import numpy as np
rng = np.random.default_rng(seed=20240501)
z = rng.standard_normal(200000)

print("均值:", z.mean())        # 期望 ≈ 0
print("标准差:", z.std())       # 期望 ≈ 1
print("偏度:", ((z - z.mean())**3).mean() / z.std()**3)   # 期望 ≈ 0
print("峰度:", ((z - z.mean())**4).mean() / z.std()**4 - 3)  # 超额峰度 ≈ 0

判断标准可参考:样本量 20 万时,均值的标准误约为 1/sqrt(200000) ≈ 0.0022,因此均值落在 ±0.005 内属正常;标准差应在 0.99~1.01 之间;偏度绝对值小于 0.02、超额峰度绝对值小于 0.05 可认为形状良好。若均值明显偏离或峰度显著为正,说明采样或生成器存在问题。

验证时建议同时画直方图并叠加理论密度曲线,以及绘制 Q-Q 图。数值指标通过但图形明显偏离(如双峰、截断),同样说明采样不合格。

采样质量对布朗运动的影响

布朗运动离散格式为 X_{t+Δt} = X_t + sqrt(Δt) * Z,其中 Z ~ N(0,1)。若 Z 的方差偏大,路径的扩散系数会被高估,均方位移 ⟨X²⟩ = 2Dt 的斜率随之偏大;若样本存在自相关,相邻步增量不独立,路径会显得“过于平滑”,均方位移曲线在长时间尺度上偏离线性。因此,采样验证不是形式主义,而是保证后续统计分析(如扩散系数估计、首次 passage time 计算)有效的前提。

均匀随机数 → 标准正态样本 → 布朗运动增量 的信号链 伪随机数生成器 种子 seed PCG64 / MT19937 输出 u ∈ [0,1) 均匀数 分布变换 Box-Muller / 逆变换 Ziggurat 拒绝采样 输出 Z ~ N(0,1) 正态样本 布朗运动增量 ΔX = √Δt · Z 路径 X(t) 累积 ⟨X²⟩ = 2Dt 统计 验证 均值 方差 不合格则回查生成器与变换 采样质量检查指标(示例阈值,样本量 2×10⁵) 均值 μ 期望 0 容差 ±0.005 标准差 σ 期望 1 容差 0.99~1.01 偏度 期望 0 |偏度| < 0.02 超额峰度 期望 0 |峰度| < 0.05

常见陷阱与排查思路

实践中几个高频问题值得注意。其一,种子复用导致相关性:在蒙特卡洛循环中若每次重新用固定种子初始化,会得到完全相同的样本序列,统计上等价于只采了一个样本。正确做法是初始化一次生成器,循环内连续取数。其二,整数溢出:手写 LCG 时若用 32 位整数做乘法,a * x_n 会溢出,必须用 64 位或更大类型。其三,均匀数取到 0:Box-Muller 中 ln(u1) 在 u1=0 时无定义,需保证 u1 > 0,或使用 1-u1 规避。其四,只看均值不看尾部:布朗运动的大偏差行为依赖正态分布的尾部,若采样被截断(如人为限制在 ±3),极端路径会被系统性低估。

排查时可按“生成器 → 变换 → 统计量”的顺序逐层定位:先单独检验均匀数序列的均值(应约 0.5)、方差(应约 1/12)和自相关(应接近 0);再检验变换后的正态样本;最后检查布朗路径的均方位移是否与 2Dt 线性吻合。逐层隔离,问题通常很快暴露。

不要用“看起来随机”作为合格标准。肉眼无法分辨的偏差,在 10⁵ 量级样本的统计检验下往往非常明显。每次更换生成器、种子策略或变换实现后,都应重新跑一遍上述指标。