yoy*_*sef 168
Jarrett建议使用Box-Muller变换对于快速而肮脏的解决方案是有益的.一个简单的实现:
Random rand = new Random(); //reuse this if you are generating many
double u1 = 1.0-rand.NextDouble(); //uniform(0,1] random doubles
double u2 = 1.0-rand.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)
Run Code Online (Sandbox Code Playgroud)
Sup*_*est 56
这个问题似乎已经转移到谷歌的.NET高斯世代,所以我想我会发一个答案.
我为.NET Random类做了一些扩展方法,包括Box-Muller变换的实现.由于它们是扩展,只要包含项目(或者您引用已编译的DLL),您仍然可以
var r = new Random();
var x = r.NextGaussian();
Run Code Online (Sandbox Code Playgroud)
希望没有人介意无耻的插头.
结果的样本直方图(包括用于绘制此结果的演示应用程序):

Gor*_*ysz 17
Math.NET提供此功能.这是如何做:
double mean = 100;
double stdDev = 10;
MathNet.Numerics.Distributions.Normal normalDist = new Normal(mean, stdDev);
double randomGaussianValue= normalDist.Sample();
Run Code Online (Sandbox Code Playgroud)
您可以在此处找到文档:http: //numerics.mathdotnet.com/api/MathNet.Numerics.Distributions/Normal.htm
我在Microsoft Connect上创建了对此类功能的请求.如果这是您正在寻找的东西,请投票支持并提高其知名度.
此功能包含在Java SDK中.它的实现作为文档的一部分提供,可以轻松移植到C#或其他.NET语言.
如果您正在寻找纯粹的速度,那么Zigorat算法通常被认为是最快的方法.
我不是这方面的专家 - 我在为RoboCup 3D模拟机器人足球库实施粒子滤波器时遇到了这个需求,并且当框架中没有包含这个时,我感到很惊讶.
同时,这里的包装器Random提供了Box Muller极地方法的有效实现:
public sealed class GaussianRandom
{
private bool _hasDeviate;
private double _storedDeviate;
private readonly Random _random;
public GaussianRandom(Random random = null)
{
_random = random ?? new Random();
}
/// <summary>
/// Obtains normally (Gaussian) distributed random numbers, using the Box-Muller
/// transformation. This transformation takes two uniformly distributed deviates
/// within the unit circle, and transforms them into two independently
/// distributed normal deviates.
/// </summary>
/// <param name="mu">The mean of the distribution. Default is zero.</param>
/// <param name="sigma">The standard deviation of the distribution. Default is one.</param>
/// <returns></returns>
public double NextGaussian(double mu = 0, double sigma = 1)
{
if (sigma <= 0)
throw new ArgumentOutOfRangeException("sigma", "Must be greater than zero.");
if (_hasDeviate)
{
_hasDeviate = false;
return _storedDeviate*sigma + mu;
}
double v1, v2, rSquared;
do
{
// two random values between -1.0 and 1.0
v1 = 2*_random.NextDouble() - 1;
v2 = 2*_random.NextDouble() - 1;
rSquared = v1*v1 + v2*v2;
// ensure within the unit circle
} while (rSquared >= 1 || rSquared == 0);
// calculate polar tranformation for each deviate
var polar = Math.Sqrt(-2*Math.Log(rSquared)/rSquared);
// store first deviate
_storedDeviate = v2*polar;
_hasDeviate = true;
// return second deviate
return v1*polar*sigma + mu;
}
}
Run Code Online (Sandbox Code Playgroud)
这是生成正态分布的随机变量的另一个快速而肮脏的解决方案。它绘制一些随机点 (x,y) 并检查该点是否位于您的概率密度函数曲线下方,否则重复。
奖励:您可以通过替换密度函数为任何其他分布(例如指数分布或泊松分布)生成随机变量。
static Random _rand = new Random();
public static double Draw()
{
while (true)
{
// Get random values from interval [0,1]
var x = _rand.NextDouble();
var y = _rand.NextDouble();
// Is the point (x,y) under the curve of the density function?
if (y < f(x))
return x;
}
}
// Normal (or gauss) distribution function
public static double f(double x, double ? = 0.5, double ? = 0.5)
{
return 1d / Math.Sqrt(2 * ? * ? * Math.PI) * Math.Exp(-((x - ?) * (x - ?)) / (2 * ? * ?));
}
Run Code Online (Sandbox Code Playgroud)
重要提示:选择y的区间和参数? 和?这样函数的曲线就不会在它的最大值/最小值点处截止(例如在 x=mean 处)。将x和y的区间视为一个边界框,曲线必须适合其中。