
正态分布随机数生成算法.doc
7页概率论与数理统计课程设计题目:正态分布随机数生成算法要编程得到服从均匀分布的伪随机数是容易的C语言、Java语言等都提供了相应的函数但是要想生成服从正态分布的随机数就没那么容易了得到服从正态分布的随机数的基本思想是先得到服从均匀分布的随机数,再将服从均匀分布的随机数转变为服从正态分布接下来就先分析三个从均匀分布到正态分布转变的方法然后编程实现其中的两个方法并对程序实现运作的效果进行统计分析1、 方法分析(1) 利用分布函数的反函数若要得到分布函数为F(x)的随机变量Y可令, 其中u是服从均匀分布的随机变量,有因而,对于任意的分布函数,只要求出它的反函数,就可以由服从均匀分布的随机变量实例来生成服从该分布函数的随机变量实例现在来看正态分布的分布函数,对于,其分布函数为:显然,要想求其反函数是相当困难的,同时要想编程实现也很复杂可见,用此种方法来生成服从正态分布的随机变量实例并不可取2) 利用中心极限定理第二种方法利用林德伯格—莱维(Lindeberg—Levi)中心极限定理:如果随机变量序列独立同分布,并且具有有限的数学期望和方差则对一切有因此,对于服从均匀分布的随机变量,只要n充分大,随机变量就服从。
我们将实现这一方法3) 使用Box Muller方法先证明:令,则令,则有接下来再来得出Box Muller方法:设为一对相互独立的服从正态分布的随机变量则有概率密度函数令,其中,则有分布函数:令如果服从均匀分布,则的分布函数即为最后,可以用代替,令为,其中,,得:从而,只需要有两个服从均匀分布的随机变量,就能通过公式来得到一个服从正态分布的随机变量用Box Muller方法来生成服从正态分布的随机数是十分快捷方便的我们也将实现这一方法2、 实现与分析(1) 利用中心极限定理方法的实现与分析利用中心极限定理来生成随机数的函数(C++语言)编写如下:const int N = 200;double getRand(){ double s = 0; for (int i = 0; i != N; ++i) s += double(rand() % 1000) / 1000; return s;}函数生成的随机数是N个[0,1]间服从均匀分布的随机数的和这里N为200从而理论上产生的随机数应近似服从,其中n为N,即200,为0.5,为1/12程序生成了200个随机数,并求出样本均值与样本方差,也即与的最大似然估计://生成随机数并存储 double sum, store[200], xi, su = 0, sb = 0, ssb = 0; int cnt = 0; sum = 0; for (int i = 0; i != 200; ++i) { xi = getRand(); sum += xi; store[i] = xi; } //得到样本均匀与样本方差 su = sum / 200; for (int i = 0; i != 200; ++i) sb += (store[i] - su) * (store[i] - su); sb /= 200; ssb = sqrt(sb); 此次选取,它们将实轴分成11个互不相交的区间,从而将样本值分成11组。
程序统计了每组中的样本数量为方便计算,程序还计算出了:int segments[12], m = 2; double x1 = 90, x10 = 108; memset(segments, 0, sizeof(segments)); for (int i = 0; i != 200; ++i) { if (store[i] <= x1) ++segments[0]; else if (store[i] > x10) ++segments[10]; else ++segments[int((store[i] - x1) / m + 1)]; } cout << 'i' << '\t' << "ni" << endl; for (int i = 0; i != 11; ++i) { cout << i + 1 << '\t' << segments[i]; if (i < 10) cout << '\t' << fixed << setprecision(2) << (90 + i * 2 - su) / ssb; cout << endl; }程序的最终运行输出如图2-1所示。
图2-1 最终输出结果对结果的统计如表2-1所示由表2-1中可见,今并令,则由于,故可认为产生的随机数服从正态分布表2-1利用中心极限定理的方法虽然可以得到服从正态分布的随机数样本,其思想也较为简单,容易想到但是这种方法每次都要先产生若干个服从均匀分布的随机数样本并求它们的和,因而算法的时间复杂度高2) Box Muller方法的实现与分析使用Box Muller方法得到随机数的函数如下:double getRand(){ double u1 = double(rand() % 10000) / 10000, u2 = double(rand() % 10000) / 10000, r; r = 20 + 5 * sqrt(-2.0 * (log(u1) / log(e))) * cos(2 * pi * u2); return r;}用此函数得到的随机数样本理论上服从所实现的程序产生了500个随机变量的样本其他与利用中心极限定理的实现基本相同程序得到的最终结果如图2-2所示图2-2对结果的统计如表2-2 所示表2-2由表2-2可见,今并令,则由于,故可认为产生的随机数服从正态分布Box Muller方法的推导过程较为复杂。
但得到的结果却是很令人满意的只要用两个相互独立的均匀分布就能得到正态分布而且产生随机数的时间复杂度比利用中心极限定理的方法要低很多因而若要产生服从正态分布的随机数样例,则Box Muller方法是一个很不错的选择。
