§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
详细情况还是看一下上传的附件“随机数产生原理”