给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
产生任意分布随机数的一般定理
产生连续型随机变量样本值的方法有如下定理:
定理:设随机变量U~U(0,1),F(x)是某一随机变量的分布函数,且F(x)为严格单调增加且连续的函数,则随机变量F-1(U)具有分布函数F(x),其中F-1(x)是F(x)的反函数。
利用该定理可以生成不同分布函数的随机变量。如随机变量X具有指数分布,其分布函数为
试产生随机变量X。X可以通过以下过程得到:
设U~U(0,1),令
解得
因为当U~U(0,1),也有1 - U~U(0,1),从而
就是所要产生的指数分布的随机变量。若有伪随机数u,就有X的随机数
正太分布随机数的生成
因为正太分布的分布函数的反函数不存在显示表达式,因此不能使用上述方法产生正太分布。下面介绍三种生成正太分布随机数的方法:
方法一:利用中心极限定理
设
且他们相互独立,由于
由中心极限定理,当n较大时近似地有
取n=12,有
这就是说,只需产生12个伪随机数,将他们加起来,再减去6,就能近似地得到标准正太变量的样本值了。又若
则利用关系式
就能得到一般的正太分布的随机变量X的样本值。
方法二:Box-Muller算法
选取两个服从[0,1]上均匀分布的随机变量U1和U2,则
是两个独立的符合标准正太分布的随机变量,关于这个算法的证明过程可参考(https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform)
在得到标准正太分布后,对于任意正太分布随机数的产生与方法一相同
方法三:ziggurat算法
Ziggurat 算法,不仅可以用于快速生成正态分布,还可以生成指数分布等等。Ziggurat 算法的基本思想是利用拒绝采样。
拒绝采样(Rejection Sampling),有的时候也称接收 - 拒绝采样,使用场景是有些函数p(x)太复杂在程序中没法直接采样,那么可以设定一个程序可抽样的分布q(x)比如正态分布等等,然后按照一定的方法拒绝某些样本,达到接近p(x)分布的目的。
Ziggurat 算法高效的秘密在于构造了一个非常巧妙的q(x),如下图所示
图片选自(https://www.zhihu.com/question/29971598)
该算法相应的伪代码如下:
j= randint(1, n); % [1,n]区间内均匀分布的随机整数
u = 2 * rand() - 1; % (-1,1)区间内均匀分布的随机浮点数
if abs(u) < sigma[j]
return u * z[j]; % u * z[j]在第j段核心区内
end
链接:https://www.zhihu.com/question/29971598/answer/53562028
由此可见,使用ziggurat算法时只需要生成一个随机整数和一个随机浮点数,做一次条件判断和一次乘法运算,外加两次查表即可得到一个服从正态分布的随机数,整个过程中没有开根号、求对数、算三角函数等复杂运算。