.net 正态分布范围内的随机数

.net 正态分布范围内的随机数,.net,.net,我想生成一个范围为(n到m,例如100到150)的随机数,但是我不想完全随机,而是希望结果基于正态分布 我的意思是,一般来说,我希望数字“聚集”在125左右 我发现这个随机数软件包似乎有很多我需要的东西: 它支持多种随机生成器(包括mersiene twister),并可将生成器应用于分发 但是我很困惑,如果我使用正态分布生成器,随机数大约是从-6到+8(显然真正的范围是float.min到float.max) 标准正态分布的平均值为0,标准偏差为1;如果你想用均值m和偏差s进行分布,只需乘以s

我想生成一个范围为(n到m,例如100到150)的随机数,但是我不想完全随机,而是希望结果基于正态分布

我的意思是,一般来说,我希望数字“聚集”在125左右

我发现这个随机数软件包似乎有很多我需要的东西:

它支持多种随机生成器(包括mersiene twister),并可将生成器应用于分发

但是我很困惑,如果我使用正态分布生成器,随机数大约是从-6到+8(显然真正的范围是float.min到float.max)


标准正态分布的平均值为0,标准偏差为1;如果你想用均值
m
和偏差
s
进行分布,只需乘以
s
,然后加上
m
。由于正态分布理论上是无限的,如果不明确拒绝超出范围的数字,就无法对范围设定硬上限,例如(100到150),但如果选择适当的偏差,则可以确保(例如)99%的数字在范围内

大约99.7%的人口在+/-3标准差范围内,所以如果你选择你的人口在
(25/3)
左右,那么这应该很有效


因此,您需要这样的东西:
(normal*8.333)+125

这对于您的需求来说可能过于简单,但是一种快速而廉价的方法可以获得一个分布向中心加权的随机数,就是简单地添加2个(或更多)随机数


想想当你掷两个六面骰子并把它们加起来的时候。总和通常是7,然后是6和8,然后是5和9,等等,很少是2或12。

tzaman的答案是正确的,但是当使用您链接的库时,有一种比自己执行计算更简单的方法:
正态分布
对象具有可写属性
Mu
(意思是平均值)和
Sigma
(标准偏差)。根据tzaman的数字,将
Mu
设置为125,将
Sigma
设置为8.333。

出于兴趣,从统一RNG生成正态分布随机数非常简单(尽管必须成对进行):

x
y
现在包含两个独立的正态分布随机数,平均值为0,方差为1。您可以根据需要对它们进行缩放和转换,以获得所需的范围(如interjay解释的)


说明:

此方法称为。它使用二维单位高斯的特性,即密度值本身,
p=exp(-r^2/2)
,均匀分布在
0
1
之间(为了简单起见,标准化常数被删除)

由于可以使用统一的RNG轻松生成这样的值,因此最终得到半径为
r=sqrt(-2*log(p))的圆形轮廓
。然后,您可以在
0
2*pi
之间生成第二个均匀随机变量,为您提供定义圆形轮廓上唯一点的角度
θ。最后,您可以通过从极坐标变换
(r,θ)来生成两个正态随机变量
返回笛卡尔坐标
(x,y)


这个属性-
p
是均匀分布的-,不适用于其他维度,这就是为什么你必须一次生成两个正态变量。

这里还有一个算法,它不需要计算Sin/Cos,也不需要知道Pi。不要问我理论背景。我发现了一些我怀疑这是@Will Vousden提到的同一个Box-Muller变换的某种归一化。它还成对产生结果

示例是VBscript;很容易转换为任何其他语言

Sub calcRandomGauss (byref y1, byref y2)
    Dim x1, x2, w
    Do
        x1 = 2.0 * Rnd() - 1.0
        x2 = 2.0 * Rnd() - 1.0
        w = x1 * x1 + x2 * x2
    Loop While w >= 1.0 Or w = 0  'edited this line, thanks Richard

    w = Sqr((-2.0 * Log(w)) / w )
    y1 = x1 * w
    y2 = x2 * w
End Sub

解决此问题的另一种方法是使用贝塔分布(与正态分布不同,贝塔分布具有硬范围),并涉及选择适当的参数,以使分布具有给定的平均值和标准偏差(方差平方根).参见。

中心极限定理意味着添加统一将近似于正态分布,但这很老套,而且很难跟踪方差。它还需要为给定的正态分布近似值采集任意数量的样本。谢谢……这很有意义:)当然,直接设置会更方便。:)+1有趣。这个方法有名字吗?我想读更多关于这方面的内容。这是一个近似值,对吗?@Drew:这叫做Box-Muller变换:谢谢。我在这里提到()建议您可以保留
u2
,并将其用作以下调用的
u1
,作为优化。维基百科的文章中没有提到这一点。你能评论一下这是否保持了随机性吗?Java的
Random.nextGaussian()
的实现看起来更像另一个答案所指的——它也声称是一个Box-Muller变换,但代码看起来与你答案中的完全不同。你在展示笛卡尔方法吗?德鲁:据我所知,生成的两个高斯随机数是完全独立的,但如果你需要确定,你应该看看更好的来源。:-)“别问我理论背景,我曾经在某个地方找到过。”。这就是错误知识传播的方式。这是Marsaglia极坐标方法的一个糟糕实现。当
w>=1.0或w==0时需要循环。否则,您将冒着使用
log(0)
的风险,并将您的程序炸毁。我会说恰恰相反。诚实地说没有任何参考资料是为了防止不正确的知识传播。谢谢你的推荐和合作
Sub calcRandomGauss (byref y1, byref y2)
    Dim x1, x2, w
    Do
        x1 = 2.0 * Rnd() - 1.0
        x2 = 2.0 * Rnd() - 1.0
        w = x1 * x1 + x2 * x2
    Loop While w >= 1.0 Or w = 0  'edited this line, thanks Richard

    w = Sqr((-2.0 * Log(w)) / w )
    y1 = x1 * w
    y2 = x2 * w
End Sub