如何将均匀分布(大多数随机数生成器产生,例如介于0.0和1.0之间)转换为正态分布?如果我想要选择的平均值和标准偏差怎么办?
该通灵塔的算法是这个相当有效,虽然箱穆勒变换更容易从头开始实现(而不是疯狂的慢).
有很多方法:
千万不能用箱穆勒.特别是如果你绘制许多高斯数字.Box Muller产生的结果夹在-6和6之间(假设是双精度.浮子会恶化).它的效率确实低于其他可用方法.
Ziggurat很好,但需要一个表查找(由于缓存大小问题,还有一些特定于平台的调整)
制服比例是我最喜欢的,只有少数加法/乘法和1/50的时间日志(例如看那里).
反转CDF 是有效的(并忽略了,为什么?),如果您搜索谷歌,您可以快速实现它.准随机数是强制性的.
将任何函数的分布更改为另一个函数涉及使用所需函数的反函数.
换句话说,如果你瞄准特定概率函数p(x),你可以通过积分得到分布 - > d(x)=积分(p(x))并使用它的逆:Inv(d(x)) .现在使用随机概率函数(具有均匀分布)并通过函数Inv(d(x))投射结果值.您应该根据您选择的函数获得随分布的随机值.
这是一般的数学方法 - 通过使用它,您现在可以选择任何概率或分布函数,只要它具有反向或良好的反向近似.
希望这有助于并感谢关于使用分布的小注释,而不是概率本身.
这是一个使用Box-Muller转换的极性形式的javascript实现.
/* * Returns member of set with a given mean and standard deviation * mean: mean * standard deviation: std_dev */ function createMemberInNormalDistribution(mean,std_dev){ return mean + (gaussRandom()*std_dev); } /* * Returns random number in normal distribution centering on 0. * ~95% of numbers returned should fall between -2 and 2 * ie within two standard deviations */ function gaussRandom() { var u = 2*Math.random()-1; var v = 2*Math.random()-1; var r = u*u + v*v; /*if outside interval [0,1] start over*/ if(r == 0 || r >= 1) return gaussRandom(); var c = Math.sqrt(-2*Math.log(r)/r); return u*c; /* todo: optimize this algorithm by caching (v*c) * and returning next time gaussRandom() is called. * left out for simplicity */ }
使用中心限制定理维基百科条目 mathworld条目对您有利.
生成n个均匀分布的数,求和,减去n*0.5,得到近似正态分布的输出,均值等于0,方差等于(1/12) * (1/sqrt(N))
(参见上一个均匀分布的维基百科)
n = 10给你一些快速的东西.如果你想要超过一半的东西去做tylers解决方案(如正常发行版的维基百科条目中所述)