我就不吃芹菜

导航

 


§1.1  
随机数的产生

§1.1.1 均匀随机数的产生

   随机变量的抽样序列称为随机数列。若随机变量是均匀分布的,则的抽样序列称为均匀随机数列;如果是正态分布的随机变量,则称其抽样序列为正态随机数列。

   用数学方法产生随机数,就是利用计算机能直接进行算术运算或逻辑运算的特点,产生具有均匀总体、简单子样统计性质的随机数。计算机利用数学方法产生随机数速度快,占用内存少,对模拟的问题可以进行复算检查,通常还具有较好的统计性质。

另外,计算机上用数学方法产生随机数,是根据确定的算法推算出来的,因此严格说来,用数学方法在计算机上产生的“随机数”不能说是真正的随机数,故一般称之为“伪随机数”。不过对这些伪随机数,只要通过统计检验符合一些统计要求,如均匀性、随机性、独立性等,就可以作为真正的随机数来使用。以后,我们统称这样产生的伪随机数为随机数。

首先给出产生均匀随机数的方法,这是产生具有其它分布随机数的基础,而后给出产生其它分布随机数的方法。

§1.1.1 均匀随机数的产生方法

线性同余法简称为LCG法(Linear Congruence Generator),它是Lehmer 于1951年提出来的。线性同余法利用数论中的同余运算原理产生随机数。分为乘同余法、混合同余法等,线性同余法是目前发展迅速且使用普遍的方法之一。

线性同余法递推公式为

                    

 

                    

                    

其中为初值,为乘子,为增量,为模,且和皆为非负整数。

当时,上式称为乘同余法公式;当时,上式称为混合同余法公式。

如下例用乘同余法产生伪随机数:

例1:

 

 

上述方法虽产生了随机数,但只产生1-10之间的数。

下列用混合同余法产生(0,1)均匀随机数。

例2:

混合同余法:

 

 

则 。

用C语言表述为:

double hrand(){

  static unsigned long x=1;

  x=(314159269L*x+453806245L)%(2147483648L);

  return((double)x/2147483648.0);

}

如产生之间的随机数,可令=2+3.

§1.1.1 均匀随机数的应用

  下面看几个具体的实例,来看一下随机数有哪些应用。

1.模拟投硬币1000次,记录正面朝上的概率及反面朝上的概率。

     (方法:用混合同余法产生1000的均匀随机数,小于0.5时即为“0”(反面),大于等于0.5是即为“1”(正面)。为0的个数除以1000即为反面朝上的概率,同理1的个数除以1000即为正面朝上的概率。)

下面是模拟正面朝上的概率程序:

#include "stdio.h"

#include "stdlib.h"

double hrand();

int main(){

       long i,count=0;

       double k;

       for(i=1;i<=10000;i++){

              k=hrand();

              if(k>0.5) {

                     count++;

              }

       }

printf("%.16lf\n",(double)count/10000.0);

return(0);

}

double hrand(){

  static unsigned long x=1;

  x=(314159269L*x+453806245L)%(2147483648L);

  return((double)x/2147483648.0);

}

运行结果:

0.4999000000000000

Press any key to continue

2.求

方法一:随机点法

#include "stdio.h"

#include "stdlib.h"

#include "math.h"

double hrand(){

  static unsigned long x=1;

  x=(314159269L*x+453806245L)%(2147483648L);

  return((double)x/2147483648.0);

}

int main(){

  long i,count=0;

  double x,y,y1;

  for(i=1;i<=1000000;i++){ 

    x=hrand();            /*x从0到1*/

    y=hrand();            /*y从0到1*/

    y1=x*x;               /*x^2在x处的值*/     

    if(y<y1) {count++;    /*落入阴影区域,就计数*/

    }

  }

  printf("%.16lf\n",(double)count/1000000.0*1);

  return(0);

}

运行结果:

0.3335010000000000

Press any key to continue

方法二:求积分也可由平均值法求得

平均值法:由  (0),

          则

用平均值法求中的积分:

令   

  则,其中  

#include "stdio.h"

#include "stdlib.h"

double hrand();

int main(){

  long i;

  double x,y,n=0,m=10000;

  for(i=1;i<=10000;i++){ 

    x=hrand();           

    y=x*x;         

    n=n+y;             

  }

  printf("%.16lf\n",(double)n/m);

  return(0);

}

double hrand(){

  static unsigned long x=1;

  x=(314159269L*x+453806245L)%(2147483648L);

  return((double)x/2147483648.0);

}

运行结果:

0.3319887679961978

Press any key to continue

作业:用两种方法(随机点法,平均值法)求dx的值。

答案:

方法一:随机点法:

#include "stdio.h"

#include "stdlib.h"

#include "math.h"

#define e 2.718281828

 

double hrand(){

  static unsigned long x=1;

  x=(314159269L*x+453806245L)%(2147483648L);

  return((double)x/2147483648.0);

}

 

int main(){

  long i,count=0;

  double x,y,y1;

  for(i=1;i<=100000;i++){ 

    x=hrand();            /*x从0到1*/

    y=hrand()*e;          /*y从0到e*/

    y1=exp(x);            /*e^x在x处的值*/     

    if(y<y1) {count++;    /*落入阴影区域,就计数*/

    }

  }

  printf("%.16lf\n",(double)count/100000.0*e);

  return(0);

}

运行结果:

1.7191773421185998

Press any key to continue

方法二:平均值法

#include "stdio.h"

#include "stdlib.h"

#include "math.h"

double hrand(){

  static unsigned long x=1;

  x=(314159269l*x+453806245l)%(2147483648l);

  return((double)x/2147483648.0);

}

main(){

  long i;

  double x,y,k,sum=0;

  for(i=1;i<=10000000;i++){ 

    x=hrand();         

    y=exp(x);        

    sum=sum+y;                  

   

  }

  k=(double)sum/10000000.0;

  printf("%.16lf\n",k);

 

}

运行结果:

1.7184117075589254

Press any key to continue

  

 

 详细情况还是看一下上传的附件“随机数产生原理”

 

 

posted on 2015-10-12 23:30  我就不吃芹菜  阅读(3254)  评论(0编辑  收藏  举报