1. 什么是数值随机化算法
数值随机化算法是一类利用随机采样来求解数值计算问题的算法。
它通常用于求解一些很难直接精确计算的问题,例如估算常数、计算定积分、估算面积、求解复杂模型的近似值等。核心思想是:
当精确求解成本很高,甚至难以实现时,可以通过大量随机样本来逼近真实结果。
数值随机化算法一般不追求”一步得到精确答案”,而是追求采样次数越多,估算结果越接近真实值。
特点数值随机化算法求的是近似解而非精确解;精度与采样次数正相关,采样越多结果越稳定;特别适合高维积分、复杂面积估算、物理系统模拟等传统方法难以精确求解的问题。
2. 随机化算法中的四种类型
随机化算法通常可以分为四类(前两类在蒙特卡罗算法一文中已经介绍过):
拉斯维加斯算法:结果一定正确,但运行时间不确定。
蒙特卡罗算法:运行时间可控,但结果可能带有误差。
舍伍德算法:引入随机性不是为了近似答案,而是为了消除最坏输入对算法性能的影响,使算法在不同输入下表现更均衡。
数值随机化算法:更关注用随机采样求数值近似解。它和蒙特卡罗方法关系很近,很多数值随机化算法就是蒙特卡罗方法在数值计算中的应用。
3. 经典问题:随机采样计算定积分
定积分是数值随机化算法中的经典应用。
假设有一个连续函数 ,要求它在区间 上的定积分:
从几何角度看,如果 ,那么这个定积分可以理解为:曲线 、 轴、直线 和 围成区域的面积。
如果这个面积很难直接计算,就可以通过随机采样来估算它。下面介绍两种经典方法。
4. 随机投点法
随机投点法的思想和蒙特卡罗估算 很像。
4.1 推导过程
假设函数 在区间 上满足 ,那么可以构造一个矩形区域 ,面积为:
在这个矩形中随机生成 个点,如果有 个点落在曲线下方(即满足 ),那么落点比例近似等于面积比例:
由此得到估算公式:
4.2 具体例子
例如函数 ,在区间 上有:
所以可以取 ,矩形区域就是 。如果随机投点后,有 个点落在曲线下方,而总共采样 个点,那么积分近似为:
这个结果就已经很接近真实值 了。
4.3 直观理解
随机投点法把积分问题转化为几何问题:
积分值 = 矩形面积 × 落点比例
矩形中均匀撒点,落在曲线下方的点越多,说明曲线下方面积占矩形面积的比例越大。当采样次数足够多时,这个比例会稳定地趋近于真实面积比。
5. 平均值法
平均值法比随机投点法更常用,也通常更稳定。
5.1 推导过程
在区间 中随机生成 个点 ,计算对应的函数值 。
这些函数值的平均数可以近似表示函数在区间上的平均高度:
而定积分可以理解为”区间长度 × 平均高度”,所以:
这就是平均值法的核心公式。
5.2 直观理解
平均值法把积分问题转化为统计问题:
积分值 = 区间长度 × 平均函数值
不需要构造矩形,也不需要生成二维随机点,只需要在一维区间上采样函数值即可。实现更简单,收敛通常也更快。
6. 示例:计算定积分
以这个积分为例:
其中 ,在区间 上满足 。
先求解析解作为对照:
代入上下限:
6.1 Java 代码实现
import java.util.Random;
public class RandomSamplingIntegral { private static final Random RANDOM = new Random();
// f(x) = 1 - x^2 private static double f(double x) { return 1 - x * x; }
// 方法一:随机投点法 public static double integralByDarts(int n) { if (n <= 0) { throw new IllegalArgumentException("采样次数必须大于 0"); }
double a = 0.0; double b = 1.0; double m = 1.0;
long count = 0;
for (int i = 0; i < n; i++) { // 在区间 [a, b] 中均匀生成 x double x = a + RANDOM.nextDouble() * (b - a);
// 在区间 [0, m] 中均匀生成 y double y = RANDOM.nextDouble() * m;
// 如果点在曲线下方,就统计到曲线下方点数中 if (y <= f(x)) { count++; } }
double rectArea = (b - a) * m; return rectArea * count / n; }
// 方法二:平均值法 public static double integralByAverage(int n) { if (n <= 0) { throw new IllegalArgumentException("采样次数必须大于 0"); }
double a = 0.0; double b = 1.0;
double sum = 0.0;
for (int i = 0; i < n; i++) { // 在区间 [a, b] 中均匀生成 x double x = a + RANDOM.nextDouble() * (b - a);
// 累加每个采样点对应的函数值 sum += f(x); }
return (b - a) * sum / n; }
public static void main(String[] args) { int samples = 1_000_000;
System.out.printf("理论解析解:%.5f%n", 2.0 / 3.0); System.out.printf("随机投点法:%.5f%n", integralByDarts(samples)); System.out.printf("平均值法:%.5f%n", integralByAverage(samples)); }}可能的输出:
理论解析解:0.66667随机投点法:0.66691平均值法:0.66654由于使用了随机数,每次运行结果可能不同。但只要采样次数足够大,两种方法的结果通常都会接近理论值 。
7. 两种方法的对比
| 方法 | 随机投点法 | 平均值法 |
|---|---|---|
| 思路 | 在矩形中随机撒点,统计落在曲线下方的比例 | 随机采样函数值,用平均函数值估算积分 |
| 核心公式 | I ≈ 矩形面积 × 落点比例 | I ≈ 区间长度 × 平均函数值 |
| 优点 | 几何意义直观,容易理解 | 实现简单,通常更稳定 |
| 缺点 | 需要知道函数上界 ,波动可能较大 | 需要理解”平均高度 × 区间长度”的思想 |
对于一维定积分来说,平均值法通常更加简洁实用。随机投点法更适合用来帮助理解”概率比例 ≈ 面积比例”这一思想,而平均值法更适合实际计算。
两种方法的时间复杂度都是 ( 为采样次数),空间复杂度都是 。这里的 不是输入规模,而是我们主动设置的采样次数。
8. 总结
数值随机化算法的核心是:
用随机采样的统计结果,去逼近某个数值答案。
在定积分问题中,随机采样有两种经典方式:
- 随机投点法:把积分看成面积,通过落点比例估算面积。
- 平均值法:把积分看成区间长度乘以平均函数值。
口诀随机投点看面积比例,平均值法看平均高度。
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时


















