资源描述
用java语言产生符合泊松分布的随机数
一、实验目的
利用随机数函数rand来产生的随机数具有一定局限性,rand函数运用线性同余法产生的是伪随机数,即每次都一样。必须加上时间作为种子,因此不直接利用rand函数
二、线性同余法的选取
同余法是Lehmer于1951年提出来的,此方法是利用数论中的同余运算原理来产生随机数,有线性同余法、非线性同余法等,其中线性同余法法又分为加同余法、乘同余法以及混合同余法。同余法是现在发展迅速且使用普遍的方法之一。首先介绍下线同余法。
线性同余法的递推式为:
式中参数和分别称为乘、增量和模,为种子。如果这些参数和种子(初值) 都指定序列也就确定下来了。通常取作为区间(O,1)上均匀分布的随机数。从上可以看出当,为乘同余法;当时,为加同余法,否则称为混合同余法。按惯例,当强调使用某方法产生随机数时,常使用某方法(随机数)发生器的称呼。
线性同余法有如下特点:
(1)。
(2)适当选取可使循环,无论取何值,其循环顺序相同,其循环周期称为发生器周期,记为。若,则称之为满周期。
(3)适当选取,可保证在[[0, 1〕区间上一个周期内每个整数正好出现一次,从而保证了均匀性。
(4)为提高的均匀性,要求加大。
下面讨论下线性同余中参数的选取。
模数的选取:
从线性同余的生成公式中可以看到,生成序列的最长周期不可能超过。为得到较长的周期,需要选择较大值。考虑的另一个方面是实现时的生成速度。
在二进制计算机上,进行模运算,最好选择模数的形式。这样模运算,只需要进行位与操作就可以实现了。但是这种简单的选择,在某些应用中,却不是令人满意的。这里,假设选取,则是的一个因子。这里的指数选取为4是因为我们假设只考察生成序列元素的最低四个比特位的规律。
可以看到,由序列的各元素低三比特位组成的序列是一个周期更短的同余序列。它的最长周期为16。类似的,低三位的最长周期为8,低五位的最长周期为32,等等。的最低位不是常数,就是O,1交替。这在强调低位随机性的应用中,是不令人满意的。 为避免这种缺陷,可以选择模数,或者是选取为小于的最大素数。对于模数的情况,有快速实现方法:
注意上述算法中,第7步其实是一个递归调用。整个算法中只有加减,位与,移位,比较和跳转操作。对于的情况也是类似的.乘数的选取模数取得较大,序列的周期才可能较大。下面的定理1指出了得到极大周期所应满足的条件:
由和所定义的线性同余序列有周期长度,当且仅当:
(1)与互素;
(2)对于整除的每个素数,是的倍数;
(3)如果,则。
在有些情况下,可能会利用来获得较快的生成速度。根据定理1,这时生成序列不可能达到极大周期聊。但仍然可以通过选择乘数来使得序列周期尽可能地长。
在生成公式中,取,,则
显然,周期是使得的最小正整数。如果与的最大公因子是,则由数论定理,得到:
由数论欧拉定理可知:
所以,必是的一个因子。欲使得为最大,应当取等于.且若与互素,则此时等于 。并且当是模的一个本原元时,中取得极大值。
综上所述,得出下面的结论:
当时,生成序列可能达到的极大周期等于模数的欧拉函数,若满足:
(1)初始值与互素;
(2)乘数 是模的一个本原元,则可以实现这一周期。
三、算法描述流程:
①.P=1;n=0;
②.产生一个[0,1]区间均匀分布随机数U.
③.P=P*U;
④.若P<=Pxmax,则返回N.
⑤.N=N+1;转步骤2.
四、运行代码及实验结果
package pangna;
public class Possion {
/**
* @param args
*/
static long seed;
static double a = 32719, m;
public static double P_rand(double Lamda) {
// 泊松分布
double n = 0, p = 1, c = Math.exp(-Lamda), u;
do {
u = randomU();
// u = Math.random();
p *= u;
System.out.println(" u=" + u + " p=" + p + " n=" + n + " c=" + c);
if (p >= c)
n++;
} while (p >= c);
return u;
}
// 线性同余法生成U【0,1)随机数
public static double randomU() {
seed = (long) ((32719 * seed) % (m - 1));
// System.out.println("seed:"+seed);
return seed / (m - 1);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
// 随机数种子生成与初始化
seed = System.currentTimeMillis();
m = Math.pow(2, 31);
double uu[] = new double[1000];
int N=1000;
// 生成10个泊松分布分布随机数
for (int i = 0; i < N; i++) {
System.out.println("第" + i + "个");
uu[i] = P_rand(0.2);
}
//计算均值与方差
double sum = 0, sum2 = 0, ave = 0, fangca = 0;
for (int i = 0; i < N; i++) {
sum = sum + uu[i];
sum2 = sum2 + uu[i] * uu[i];
System.out.println("u:" + i + ":" + uu[i]);
}
ave = (double) sum / N;
System.out.println("均值:" + ave);
for (int i = 0; i < N; i++) {
// sum = sum + uu[i];
sum2 = sum2 + (uu[i] - ave) * (uu[i] - ave);
}
fangca = sum2 / N;
System.out.println("方差:" + fangca);
}
}
通过随机性检验,得到均值和方差在预想值附近,得到以下实验结果:
四.结果分析
线性同余法不仅与种子有关,而且与参数m,a,c的选取有关。为了保证其统计性质,一般将m取得很大.这样,在计算过程中,为防止整数溢出还要进行一些算法处理。此次作业让我们了解学习了更多的东西,收益匪浅。
展开阅读全文