欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

蒙特卡洛方法

程序员文章站 2022-07-11 09:09:52
...

目录

一,蒲丰投针问题(Buffon's noodle)

二,求定积分

三,求反常积分

1,*函数反常积分

2,无穷区间反常积分

四,其他蒙特卡洛方法


一,蒲丰投针问题(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

 

相关标签: new