蒙特·卡罗方法(Monte Carlo method),也称统计模拟方法,是二十世纪四十年代中期由于科学技术的发展和电子计算机的发明,而被提出的一种以概率统计理论为指导的一类非常重要的数值计算方法。是指使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。与它对应的是确定性算法。蒙特·卡罗方法在金融工程学,宏观经济学,计算物理学(如粒子输运计算、量子热力学计算、空气动力学计算)等领域应用广泛[1]。
使用蒙特·卡罗方法求圆周率。
如下图所示,随机生成大量的点都在矩形区域内,然后会有部分点落在圆内,两者的比值基本等于面积比值。以此为关系,建立公式求出PI的值。
给定集合两个点的集合S1和S2如下所示。
S 1 = { ( x , y ) ∣ x ∈ [ − 1 , 1 ] , y ∈ [ − 1 , 1 ] } S 2 = { ( x , y ) ∣ x 2 + y 2 ≤ 1 } S1 = \{(x,y) | x∈[-1,1], y ∈ [-1, 1] \}\\ S2 = \{(x,y) | x^2 + y^2 ≤ 1\} S1={ (x,y)∣x∈[−1,1],y∈[−1,1]}S2={ (x,y)∣x2+y2≤1}
其中,S1表示下图中矩形内的所有点,S2表示下图所示圆内的所有点。
利用蒙特·卡罗方法,随机生成 M个落在S1内的点,设这些点中落在S2中的点有N个。由于随机生成的点是平均分布在区域内的,所以矩形面积与圆形面积的比值可以近似表示为 N/M(当M趋于无穷大时可以取等号)。所以可得
π r 2 / ( 2 r ) 2 = S 1 / S 2 ≈ N / M \pi r^2/(2r)^2 = S1/S2 \approx N/M πr2/(2r)2=S1/S2≈N/M
利用最左右两式化简后可得
π = 4 N / M \pi = 4N/M π=4N/M
整个代码编写使用Java实现,代码附在文章尾。
原始整理的数据参见附录2。对结果进行统计分析数据如下
测试 | 1M | 10M | 100M | 1000M | 10000M |
---|---|---|---|---|---|
平均值 | 3.141794181818 | 3.141524254545 | 3.141551778182 | 3.141571543273 | 3.141580096378 |
与PI绝对误差 | 2.0153E-04 | 6.8399E-05 | 4.0875E-05 | 2.1110E-05 | 1.2557E-05 |
方差 | 1.2234E-03 | 3.9009E-04 | 1.5801E-04 | 4.8368E-05 | 3.5344E-05 |
根据以上结果我们可以看到:
[1] 蒙特·卡罗方法, 百度百科, https://baike.baidu.com/item/蒙特·卡罗方法.
public class Test{
public static void main(String[] args) {
int[] mts = {
1, 10, 100, 1000, 10000 };
for (int test = 0; test < mts.length; test++) {
for (int runTimes = 0; runTimes < 11; runTimes++) {
long t1 = System.currentTimeMillis();
double pi = calPI(mts[test]);
long t2 = System.currentTimeMillis();
System.out.printf("%d\t%.12f\t%d\n", mts[test], pi, t2 - t1);
}
}
}
static double calPI(int mtimes) {
long totalTimes = mtimes * 1000 * 1000;
long count = 0;
for (int i = 0; i < totalTimes; i++) {
double x = Math.random() * 2 - 1;
double y = Math.random() * 2 - 1;
if (x * x + y * y <= 1)
count++;
}
return 4.0 * count / totalTimes;
}
}
实验结果整理如下。
测试 | 1M | 10M | 100M | 1000M | 10000M |
---|---|---|---|---|---|
测试1 | 3.142360000000 | 3.140679200000 | 3.141713720000 | 3.141578804000 | 3.141550627983 |
测试2 | 3.141624000000 | 3.141345600000 | 3.141670440000 | 3.141563544000 | 3.141606392772 |
测试3 | 3.140448000000 | 3.141157600000 | 3.141164000000 | 3.141456096000 | 3.141563572064 |
测试4 | 3.142236000000 | 3.141332400000 | 3.141526360000 | 3.141613740000 | 3.141643920110 |
测试5 | 3.143396000000 | 3.141452400000 | 3.141528480000 | 3.141518756000 | 3.141553674651 |
测试6 | 3.140520000000 | 3.142040400000 | 3.141332640000 | 3.141573840000 | 3.141586141230 |
测试7 | 3.142640000000 | 3.141797200000 | 3.141588600000 | 3.141583848000 | 3.141533528067 |
测试8 | 3.142236000000 | 3.141986800000 | 3.141593600000 | 3.141609088000 | 3.141603950332 |
测试9 | 3.143776000000 | 3.141757600000 | 3.141688680000 | 3.141602520000 | 3.141629583186 |
测试10 | 3.139856000000 | 3.141356000000 | 3.141621560000 | 3.141639432000 | 3.141572680861 |
测试11 | 3.140644000000 | 3.141861600000 | 3.141641480000 | 3.141547308000 | 3.141536988900 |