数学建模算法 一 简述(1)蒙特卡洛算法

蒙特卡罗方法概述

蒙特卡罗方法又称统计模拟法、随机抽样技术,是一种随机模拟方法,以概率和统计理论方法为基础的一种计算方法,是使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。将所求解的问题同一定的概率模型相联系,用电子计算机实现统计模拟或抽样,以获得问题的近似解。为象征性地表明这一方法的概率统计特征,故借用赌城蒙特卡罗命名。

通俗的讲:
蒙特卡罗算法:采样越多,越近似最优解

举个例子:假如筐里有100个苹果,闭眼拿1个,挑出最大的。于是我随机拿1个,再随机拿1个跟它比,留下大的,再随机拿1个……每拿一次,留下的苹果都至少不比上次的小。拿的次数越多,挑出的苹果就越大,但我除非拿100次,否则无法肯定挑出了最大的。这个挑苹果的算法,就属于蒙特卡罗算法——尽量找好的,但不保证是最好的。

【例】用蒙特卡洛模拟法求圆周率pi
如图,红色线条为平面上圆心在原点的单位圆,圆的面积为pi,黑色线条构成边长为2的正方形
《数学建模算法 一 简述(1)蒙特卡洛算法》
设相互独立的随机变量X,Y均服从[-1,1]上的均匀分布,则(X,Y)服从{-1≤x≤1, -1≤y≤1}上的二元均匀分布(即图中正方形区域上的二元均匀分布),记事件A = {x^2+y^2≤1},则A事件发生的概率等于单位圆面积除以边长为2的正方形的面积,即P(A) = pi/4。

可得圆周率pi = 4P(A). 而P(A)可以通过蒙特卡洛模拟法求得,在图1中正方形内随机投点(即横座标X和纵座标Y都是[-1,1]上均匀分布的随机数),落在单位圆内的点的个数m与点的总数n的比值m/n可以作为A事件的概率P(A)的近似,随着投点总数的增加,m/n会越来越接近于P(A),从而可以得到逐渐接近于pi的模拟值
MATLAB代码

    %总的实验次数 
    n = input('请输入n:');  
    %落在圆中点的次数 
    m = 0;  
    %使用的圆的半径 
    a = 2;  
    %循环实验 
    for i = 1:n  
        x = rand * a / 2;  %产生随机数
        y = rand * a / 2;  
        if (x^2 + y^2 <= (a/2)^2)  
            m = m + 1;  
        end  
    end  
    %显示结果 
    fprintf('当总实验次数n = %d时计算出来的圆周率:Pi = %d\n',n, 4 * m / n);  
C
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main()
{
    unsigned long i;
    unsigned long m;
    const unsigned long N=100000000;
    double x,y,pi;
    srand((unsigned)time(NULL));
    for(i=0,m=0;i<N;i++)
    {
        /*x,y在区间(-1,1)*/
        x=2.0*rand()/RAND_MAX-1;、/*产生– 1到1之间的随机数*/
        y=2.0*rand()/RAND_MAX-1;
        if((x*x+y*y)<=1)
        { 
              m++;
        }
    }
    pi=4.0*m/N;
    printf("%lf\n",pi);
    return 0;
}

srand((unsigned)time(NULL))作用

1、随机数是由随机种子根据一定的计算方法计算出来的数值。所以,只要计算方法一定,随机种子一定,那么产生的随机数就不会变。
2、只要用户或第三方不设置随机种子,那么在默认情况下随机种子来自系统时钟(即定时/计数器的值)
3、建议:如果想在一个程序中生成随机数序列,需要至多在生成随机数之前设置一次随机种子。 也就是只需在主程序开始处调用srand((unsigned)time(NULL)); 后面直接用rand就可以了。不要在for等循环放置srand((unsigned)time(NULL));

点赞