最近我们死策划来了个需求,要求产生的随机数符合正态分布。而且要截断正态分布。
查阅erlang文档。发现rand模块有这么两个函数。
normal() -> float()
Returns a standard normal deviate float (that is, the mean is 0 and the standard deviation is 1) and updates the state in the process dictionary.
normal(Mean :: number(), Variance :: number()) -> float()
Returns a normal N(Mean, Variance) deviate float and updates the state in the process dictionary.
第一个是产生符合标准正态分布的随机数。第二个带参的是产生一个均值为Mean,方差为Variance的正态分布随机数。
一看第二个函数就是我想要的啊。废话不说,马上实验一下。
rand:normal(50, 15).
** exception error: undefined function rand:normal/2
excuse me? 你这是在逗我吗?报错。
可能我的Erlang版本太低了吧。
不过别担心,我们还有别的办法。至少我们的 rand:normal() 这个函数是可以使用的,它可以给我们产生一个符合标准正态分布的随机数出来。
那么
rand:normal() * 方差 + 均值(期望值)
这样就可以产生一个均值为Mean, 方差为Variance的正态分布随机数。
下图为产生一个期望50,方差15的正态分布。
截断正态分布
实现了以上正态分布,差不多就是我们要的了。
但是我们死策划说。产生的随机数值得在某一个正态分布区间内?
这个就是截断正态分布。
按照策划的意思就是,按照这个这个正态分布随机函数,一直生成。直到生成落在这个区间的随机数值为止?
当然我们肯定不能这样做?我们需要一次性就能把这个随机数生成出来,这样不仅提高了性能?而且不会有什么隐含的bug存在?
1、先生成符合正太分布随机函数的样本
2、在这个样本中把符合区间的数值取出来
3、在这些数值中随机出一个值
只要样本数据越大,那么这个就越准确。
这应该是一种最笨的办法吧?
如果你有更好的解决方案,欢迎和我交流。