欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

给定均值和方差,不使用库函数生成1000个符合正太分布的随机数

程序员文章站 2024-03-25 21:09:40
...

产生任意分布随机数的一般定理

产生连续型随机变量样本值的方法有如下定理:
定理:设随机变量U~U(0,1),F(x)是某一随机变量的分布函数,且F(x)为严格单调增加且连续的函数,则随机变量F-1(U)具有分布函数F(x),其中F-1(x)是F(x)的反函数。

利用该定理可以生成不同分布函数的随机变量。如随机变量X具有指数分布,其分布函数为
给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
试产生随机变量X。X可以通过以下过程得到:
设U~U(0,1),令
给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
解得
给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
因为当U~U(0,1),也有1 - U~U(0,1),从而
给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
就是所要产生的指数分布的随机变量。若有伪随机数u,就有X的随机数给定均值和方差,不使用库函数生成1000个符合正太分布的随机数

正太分布随机数的生成

因为正太分布的分布函数的反函数不存在显示表达式,因此不能使用上述方法产生正太分布。下面介绍三种生成正太分布随机数的方法:

方法一:利用中心极限定理


给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
且他们相互独立,由于
给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
由中心极限定理,当n较大时近似地有

给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
取n=12,有
给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
这就是说,只需产生12个伪随机数,将他们加起来,再减去6,就能近似地得到标准正太变量的样本值了。又若给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
则利用关系式
给定均值和方差,不使用库函数生成1000个符合正太分布的随机数

就能得到一般的正太分布的随机变量X的样本值。

方法二:Box-Muller算法

选取两个服从[0,1]上均匀分布的随机变量U1和U2,则

给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
是两个独立的符合标准正太分布的随机变量,关于这个算法的证明过程可参考(https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform)
在得到标准正太分布后,对于任意正太分布随机数的产生与方法一相同

方法三:ziggurat算法

Ziggurat 算法,不仅可以用于快速生成正态分布,还可以生成指数分布等等。Ziggurat 算法的基本思想是利用拒绝采样
拒绝采样(Rejection Sampling),有的时候也称接收 - 拒绝采样,使用场景是有些函数p(x)太复杂在程序中没法直接采样,那么可以设定一个程序可抽样的分布q(x)比如正态分布等等,然后按照一定的方法拒绝某些样本,达到接近p(x)分布的目的。
Ziggurat 算法高效的秘密在于构造了一个非常巧妙的q(x),如下图所示
给定均值和方差,不使用库函数生成1000个符合正太分布的随机数
图片选自(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算法时只需要生成一个随机整数和一个随机浮点数,做一次条件判断和一次乘法运算,外加两次查表即可得到一个服从正态分布的随机数,整个过程中没有开根号、求对数、算三角函数等复杂运算。