蒙特卡洛模型之神奇的布丰投针实验

【问题的提出】
18世纪,法国数学家布丰(1707-1788)提出提出了一种计算圆周率的方法——随机投针法,即蒲丰投针问题(又译“布丰投针问题”)
(如图)
蒙特卡洛模型之神奇的布丰投针实验_第1张图片
实验步骤
布丰的实验步骤如下:
1) 取一张白纸,在上面画上许多条间距为a的平行线。
2) 取一根长度为l(l≤a) 的针,随机地向画有平行直线的纸上掷n次,观察针与直线相交的次数,记为m。
3)计算针与直线相交的概率.
18世纪,法国数学家布丰提出的“投针问题”,记载于布丰1777年出版的著作中:“在平面上画有一组间距为a的平行线,将一根长度为l(l≤a)的针任意掷在这个平面上,求此针与平行线中任一条相交的概率。”
布丰本人证明了,这个概率是:
 (其中π为圆周率)
(其中π为圆周率)
由于它与π有关,于是人们想到利用投针试验来估计圆周率的值。
布丰惊奇地发现:有利的扔出与不利的扔出两者次数的比,是一个包含π的表示式.如果针的长度等于a/2,那么有利扔出的概率为1/π.扔的次数越多,由此能求出越为精确的π的值。
蒙特卡洛法介绍
蒙特卡罗法又称统计模拟法,是一种以抽样和随机数的产生为基础的随机性方法,因此也称为随机抽样法、计算机随机模拟法等。蒙特卡罗方法的基本原理是通过数字模拟试验,得到所要求解的出现某种事件的概率,作为问题的近似解。很久之前人们就已经开始使用蒙特卡罗方法来解决问题了,早在17世纪,发生事件的概率是用发生事件的频率来决定的。在20世纪计算机的使用,使得这样的实验可以大量快速的进行模拟。近年来,随着蒙特卡罗方法不仅被用于数学、物理、化学等领域,还应用于核科学与技术、机械工程、天文学和仪器科学与技术等。该法产生了不同的分支,有直接蒙特卡罗法,动力学蒙特卡罗法等
本题思路
由于蒙特卡罗法是基于概率论思想,因此可适用在布丰投针实验中。经过次数足够大的实验,针与平行线相交的概率即为实验中该现象发生的频率。
那么如何与π相联系呢?
(如图)

注:图片来自网络
图片中的解决思路即将为针与平行线的关系转化为面积之比的关系,问题也随之转化为了求解概率问题。
【matlab求解思路】
可将针与平行线相交转化为数学公式1即:
公式1
实验重复次数可为n=1:10000(按自己需求)
判断上式是否成立,若成立,则m=m+1(m为相交次数,初始可为0)
直至循环结束
则频率(概率)为:
在这里插入图片描述
再根据公式1,将p带入,得出π的近似值。
*****实际问题转化为数学语言表述
【代码部分(matlab)】

l =  0.502;     % 针的长度(任意给的)
a = 1.4;    % 平行线的宽度(大于针的长度l即可)
n = 1000000;    % 做n次投针试验
m = 0;    % 记录针与平行线相交的次数
x = rand(1, n) * a / 2 ;   % 在[0, a/2]内服从均匀分布随机产生n个数, x中每一个元素表示针的中点和最近的一条平行线的距离
fai= rand(1, n) * pi;    % 在[0, pi]内服从均匀分布随机产生n个数,phi中的每一个元素表示针和最近的一条平行线的夹角
% axis([0,pi, 0,a/2]);   box on;  % 画一个坐标轴的框架,x轴位于0-pi,y轴位于0-a/2, 并打开图形的边框
for i=1:n  % 开始循环,依次看每根针是否和直线相交
    if x(i) <= l / 2 * sin(phi (i))     % 如果针和平行线相交
        m = m + 1;    % 那么m就要加1
         plot(fai(i), x(i), 'r.')   % 模仿书上的那个图,横坐标为phi,纵坐标为x , 用红色的小点进行标记
         hold on  % 在原来的图形上继续绘制
    end
end
p = m / n;    % 针和平行线相交出现的频率
mypi = (2 * l) / (a * p);  % 我们根据公式计算得到的pi
disp(['蒙特卡罗方法得到pi为:', num2str(mypi)])%输出结果


也可多次求解,求其平均值,提高准确率
代码如下:

result = zeros(100,1);  % 初始化保存100次结果的矩阵
l =  0.520;     a = 1.314;
n = 1000000;    
for num = 1:100
    m = 0;  
    x = rand(1, n) * a / 2 ;
    phi = rand(1, n) * pi;
    for i=1:n
        if x(i) <= l / 2 * sin(phi (i))
            m = m + 1;
        end
    end
    p = m / n;
    mypi = (2 * l) / (a * p);
    result(num) = mypi;  % 把求出来的myphi保存到结果矩阵中
end
mymeanpi = mean(result);  % 计算result矩阵中保存的100次结果的均值
disp(['蒙特卡罗方法得到pi为:', num2str(mymeanpi)])

感悟:首先是知道了前辈们求解圆周率π的另一种方法,即基于多次试验的统计结果,这给今后解决问题提供了一个思路。其次,通过投针试验,大致了解了蒙特卡洛法的基本思路,其主要的思想便是在不知道问题的本质求解的方法时,可通过多次试验,从实验中的概率统计结果中找到问题的近似解。另外,在编程实现方面,虽然有一定的matlab基础,但是对于具体的思路的实现仍较为困难,通过看建模视频中提出的各个问题,跟上思路,积极思考,多看代码多学习,我想一段时间后,编程解决问题的能力还是可以提高的,在此感谢清风大哥!

你可能感兴趣的:(matlab,概率论,算法)