目录
一、什么是蒙特卡洛方法
二、蒙特卡洛方法的基本思想
三、用蒙特卡洛方法求圆周率 π
四、用蒙特卡洛方法求定积分
你听说过 "蒙特卡洛法" 吗?哦,那是一种计算不规则图形面积的计算机程序算法,具体做法是在软件中用大量的小球随机击打那块不规则图形,被击中的地方不再重复打击,这样,达到一定的数量后,图形的所有部分就会都被击中一次,这时统计图形区域内小球的数量,就得到了图形的面积,当然,球越小结果越精确。
这种方法虽然简单,却展示了数学中的一种用随机的蛮力对抗精确逻辑的思想方法,一种用数量得到质量的计算思想。这就是我解决三体问题的策略。
一、什么是蒙特卡洛方法
蒙特卡洛方法(Monte Carlo method)也称统计模拟方法,是 1940 年代中期由于科学技术的发展和电子计算机的发明,而提出的一种以概率统计理论为指导的数值计算方法,是指使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。
20 世纪 40 年代,在冯·诺依曼,斯塔尼斯拉夫·乌拉姆和尼古拉斯·梅特罗波利斯在洛斯阿拉莫斯国家实验室为核武器计算工作时,发明了蒙特卡洛方法。因为乌拉姆的叔叔经常在摩纳哥的蒙特卡洛赌场输钱而得名,而蒙特卡洛方法正是以概率为基础的方法,与它对应的时确定性算法。
二、蒙特卡洛方法的基本思想
通常蒙特卡洛方法可以粗略地分成两类:一类是所求解的问题本身具有内在的随机性,借助计算机的运算能力可以直接模拟这种随机的过程。例如在核物理研究中,分析中子在反应堆中的传输过程。中子与原子核作用受到量子力学规律的制约,人们只能知道它们相互作用发生的概率,却无法准确获得中子与原子核作用时的位置以及裂变产生的新中子的行进速率和方法。科学家依据其概率进行随机抽样得到裂变位置、速度和方向,这样模拟大量中子的行为后,经过统计就能获得中子传输的范围,作为反应堆设计的依据。
另一种类型是所求解问题可以转换为某种随机分布的特征数,比如随机事件出现的概率,或者随机变量的期望值。通过随机抽样的方法,以随机事件出现的频率估计其概率,或者以抽样的数字特征估算随机变量的数字特征,并将其作为问题的解。这种方法多用于求解复杂的多维积分问题。
三、用蒙特卡洛方法求圆周率 π
正方形内部有一个四分之一圆,圆和正方形的面积之比是 π / 4。现在,在这个正方形内部,随机产生 n 个点,计算它们与圆心的距离,并且判断是否落在圆的内部。若这些点均匀分布,则圆周率 π = 4 * in_circle / n,其中 in_circle 表示落在圆内的点数。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
double GetPi(const int n)
{
srand((unsigned int)time(NULL));
double x = 0.0;
double y = 0.0;
int in_circle = 0;
for (int i = 0; i < n; ++i)
{
x = (double)rand() / RAND_MAX;
y = (double)rand() / RAND_MAX;
if (x * x + y * y < 1.0)
{
++in_circle;
}
}
return 4.0 * in_circle / n;
}
int main()
{
printf("%lf\n", GetPi(100000));
return 0;
}
四、用蒙特卡洛方法求定积分
例如我们想求 的值。
int main()
{
const int n = 100000;
srand((unsigned int)time(NULL));
double x = 0.0;
double y = 0.0;
int count = 0;
for (int i = 0; i < n; ++i)
{
x = (double)rand() / RAND_MAX;
y = (double)rand() / RAND_MAX;
if (y < x * x) // y < x * x 表示该点位于曲线下面
{
++count;
}
}
printf("%lf\n", 1.0 * count / n);
return 0;
}
参考资料:初学者都能看懂的蒙特卡洛方法以及python实现_蒙特卡洛算法