我想生成一个范围内的随机数(n到m,如100到150),但不是纯粹的随机,我希望结果是基于正态分布。
我的意思是,一般来说,我希望数字“聚集”在125周围。
我发现这个随机数包似乎有很多我需要的东西:http://codeproject.com/KB/recipes/Random.aspx
它支持多种随机数生成器(包括mersiene twister),并可以将生成器应用于分布。
但我很困惑,如果我使用正态分布生成器,随机数大约在-6到+8之间(显然真正的范围是float.min到float.max)。
如何将其缩放到所需范围?
6条答案
按热度按时间nfzehxib1#
标准正态分布的均值为0,标准差为1;如果你想得到一个平均值为
m
,偏差为s
的分布,只需乘以s
,然后加上m
。由于正态分布理论上是无限的,你不能在你的范围上设置一个硬性上限,例如(100到150)而不显式地拒绝落在它之外的数字,但是通过适当选择偏差,可以确保(例如)99%的数字将在该范围内。大约99.7%的人口在+/- 3个标准差之内,所以如果你选择你的大约是
(25/3)
,它应该工作得很好。所以你需要这样的东西:
(normal * 8.333) + 125
64jmpszr2#
出于兴趣,从均匀RNG生成正态分布的随机数非常简单(尽管必须成对进行):
x
和y
现在包含两个独立的正态分布随机数,平均值为0,方差为1。您可以根据需要缩放和转换它们,以获得所需的范围(正如interjay所解释的)。这种方法被称为Box–Muller transform,它利用了二维单位高斯的性质,即密度值
p = exp(-r^2/2)
均匀分布在0
和1
之间(为简单起见,去掉了归一化常数)。由于可以使用均匀RNG轻松生成这样的值,因此最终会得到半径为
r = sqrt(-2 * log(p))
的圆形轮廓。然后可以在0
和2*pi
之间生成第二个均匀随机变量,以获得定义圆形轮廓上唯一点的Angularθ
。最后,通过从极坐标(r, θ)
变换回笛卡尔坐标(x, y)
,可以生成两个i.i.d.正态随机变量。p
是均匀分布的这一性质对其他维度不成立,这就是为什么你必须一次生成恰好两个正态变量。7jmck4yq3#
tzaman的答案是正确的,但是当使用链接的库时,有一种比自己执行计算更简单的方法:
NormalDistribution
对象具有可写属性Mu
(表示平均值)和Sigma
(表示标准差),因此根据tzaman的数字,将Mu
设置为125,将Sigma
设置为8.333。a5g8bdjr4#
这对于您的需要来说可能过于简单,但是要获得一个具有向中心加权的分布的随机数,一种快速而廉价的方法是简单地添加2个(或更多)随机数。
想一想当你掷两个6面骰子并把它们相加时,总和最常见的是7,然后是6和8,然后是5和9,等等,很少有2或12。
pnwntuvh5#
解决这个问题的另一种方法是使用 *beta分布 *(与正态分布不同,它有一个硬范围),并选择适当的参数,使分布具有给定的均值和标准差(方差的平方根)。
h5qlskok6#
这里有另一个算法,它不需要计算Sin/Cos,也不需要知道Pi。不要问我理论背景。我曾经在某个地方找到过它,从那以后我一直在使用它。我怀疑它是@Will Vousden提到的同一个Box-Muller变换的某种归一化。它也会成对产生结果。
示例是VBscript;很容易转换成其他语言。