zoukankan      html  css  js  c++  java
  • 随机数产生原理


    §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 ",(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 ",(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 ",(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 ",(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 ",k);

    }

    运行结果:

    1.7184117075589254

    Press any key to continue

      

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

     

     

  • 相关阅读:
    android下socket编程问题:服务器关闭时,客户端发送请求的异常处理
    MySQL新建用户,授权,删除用户,修改密码
    jquery验证表单代码
    Incorrect key file for table '/tmp/#sql_46fd_0.MYI'; try to repair it
    初试百度地图API
    Android控件之GridView探究
    使用Intent调用内置应用程序
    消除SDK更新时的“https://dl-ssl.google.com refused”错误
    A folder failed to be renamed or moved--安装Android SDK的问题
    windows下搭建svn服务器
  • 原文地址:https://www.cnblogs.com/wgbs25673578/p/4873269.html
Copyright © 2011-2022 走看看