正态分布随机数⽣成法(java版)
要编程得到服从均匀分布的伪随机数是容易的。C语⾔、Java语⾔等都提供了相应的函数。但是要想⽣成服从正态分布的随机数就没那么容易了。
得到服从正态分布的随机数的基本思想是先得到服从均匀分布的随机数,再将服从均匀分布的随机数转变为服从正态分布。接下来就先分析三个从均匀分布到正态分布转变的⽅法。然后编程实现其中的两个⽅法并对程序实现运作的效果进⾏统计分析。
1、⽅法分析
(1)利⽤分布函数的反函数
若要得到分布函数为F(x)的随机变量Y。
可令,其中u是服从均匀分布的随机变量,有
因⽽,对于任意的分布函数,只要求出它的反函数,就可以由服从均匀分布的随机变量实例来⽣成服从该分布函数的随机变量实例。
现在来看正态分布的分布函数,对于
,其分布函数为:
显然,要想求其反函数是相当困难的,同时要想编程实现也很复杂。可见,⽤此种⽅法来⽣成服从正态分布的随机变量实例并不可取。
(2)利⽤中⼼极限定理
第⼆种⽅法利⽤林德伯格—莱维(Lindeberg—Levi)中⼼极限定理:如果随机变量序列
独⽴同分布,并且具有有限的数学期望和⽅差
则对⼀切x∈R有
因此,对于服从均匀分布的随机变量Xi,只要n充分⼤,随机变量
为正态分布。我们将实现这⼀⽅法。这⾥ Ri为[0,1]之间均匀分布的随机数
package cn.tan.basicmath;
/**
*
* @author Özil ισνΞ
*
*/
public class RanZT {
/**
* 这⾥是我上⼀篇⽇记⾥⾯产⽣[0,1]随机数的算法
* @param r 将变量的地址传进函数中,以便每次调⽤后更新随机种⼦的值,否则将得到完全⼀样的数据从⽽失去随机性
* 这⾥r我们初始化为5
* @return
*/
static double seftRandom(double[] r){
double base,u,v,p,temp1,temp2,temp3;
//基数
base = 256.0;
//两个常数 uv;
u = 17.0;
v = 139.0;
//计算总值
temp1 = u*(r[0])+v;
//计算商
temp2 = (int)(temp1/base);
//计算余数,1到base的余数
//计算余数,1到base的余数
temp3 = temp1 - temp2*base;
//更新随机种⼦,为下⼀次使⽤
r[0] = temp3;
/
/随机数赋值,获取[0,1]的随机数
p = r[0]/base;
return p;
}
/**
* 正态分布随机数⽣成法
* @param u 正态分布的均值
* @param t 正态分布的⽅差0
* @param r 随机种⼦
* @param n 正态分布公式的n
* @return
*/
static double randZT(double u,double t,double[]r,double n){  int i;
double total = 0.0;
double result;
for(i = 0;i<n;i++){
//累加
total += seftRandom(r);
java生成随机数的方法
}
//得到的随机数
result = u+t*((total-n/2.0)/Math.sqrt(n/12));
return result;
}
public static void main(String[] args){
int i;
double u,t,n;
double[] r = {5.0};
//初始化正态分布的均值和⽅差
u = 2.0;
t = 3.5;
n = 12.0;
System.out.println("产⽣⼗个正态分布的随机数:");
//循环调⽤
for(i = 0;i<10;i++){
System.out.printf("%10.5f\n",randZT(u,t,r,n));
}
System.out.println();
}
}