蒙特卡洛方法
目录
一,蒲丰投针问题(Buffon's noodle)
平面内有无穷多条互相平行的直线,任意相邻两条的彼此间隔都是a,
有一条长为l的针,l<=a,把针随机丢在平面内,求针和直线有交点的概率。
解法一:
其中的思想是,针的质心的位置和针的方向是两个独立的随机变量。
所以,投针实验可以用来估算π的值。
解法二:
一个直径为a的圆和直线组的交点数量的均值为2,
所以直径为l/π的圆和直线组的交点数量的均值为
所以长为l的线段和直线组的交点数量的均值为
因为交点数大于1的概率为0,所以交点数等于1的概率就是
其中的思想是,交点的数量只和曲线长度有关,而且成正比,与曲线形状无关,证明思路是用折线逼近曲线,
但是总感觉这个证明非常不严谨,因为再短的线段也可能和直线有无穷多交点,这种情况是存在的,只是概率为0,而这种情况对交点数的期望的贡献是否为0?
这个问题可以抽象出一个更简单的核心问题:线段如果就是平行于直线的,但是位置是均匀随机的,那我们是不是可以认为交点个数的均值是线段长度除以a?
关于这方面,可以了解下 Geometric probability,本文不展开讨论了。
二,求定积分
要求,可以在区间[a,b]内产生n个随机数,计算
当n越来越大时,它就去趋近于I
例如,求
代码:
#include<iostream>
#include<time.h>
using namespace std;
int main()
{
srand(time(NULL));
int N=30000,num=0;
double s=0;
for(int i=0;i<100000;i++){
int x=rand();
if(x>=N)continue;
s+=1/(x*1.0/N+1),num++;
}
cout<<s/num;
return 0;
}
输出:
0.693811
实际上,I=ln2=0.69314718,误差还是比较小的。
这里为了保证随机数的质量,采用了拒绝采样 https://blog.csdn.net/nameofcsdn/article/details/116537214
三,求反常积分
1,*函数反常积分
*函数反常积分的表达式和定积分完全相同,所以用蒙特卡洛方法来求的步骤也是一样的。
例如,求
代码:
#include<iostream>
#include<time.h>
#include<math.h>
using namespace std;
int main()
{
srand(time(NULL));
int N=30000,num=0;
double s=0;
for(int i=0;i<1000000;i++){
int x=rand();
if(x>=N)continue;
s+=1/sqrt((x+1)*1.0/N),num++;
}
cout<<s/num;
return 0;
}
输出:
1.98922
实际上,I=2,误差还是比较小的。
2,无穷区间反常积分
设f的反函数是g,则,参考https://blog.csdn.net/nameofcsdn/article/details/116570653
例如,求
根据公式,反函数,把I化成*函数反常积分
其中 上面已经求过了是2,所以I=1
四,其他蒙特卡洛方法
https://blog.csdn.net/nameofcsdn/article/details/115269170
上一篇: matplotlib的安装历程
下一篇: impala的保留关键字,建表时慎用