C# 随机高斯变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/218060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Random Gaussian Variables
提问by Sebastian Müller
Is there a class in the standard library of .NET that gives me the functionality to create random variables that follow Gaussian distribution?
.NET 标准库中是否有一个类可以让我创建遵循高斯分布的随机变量?
采纳答案by yoyoyoyosef
Jarrett's suggestion of using a Box-Muller transform is good for a quick-and-dirty solution. A simple implementation:
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)
回答by David Arno
I don't think there is. And I really hope there isn't, as the framework is already bloated enough, without such specialised functionality filling it even more.
我不认为有。我真的希望没有,因为框架已经足够臃肿,没有这种专门的功能来填充它。
Take a look at http://www.extremeoptimization.com/Statistics/UsersGuide/ContinuousDistributions/NormalDistribution.aspxand http://www.vbforums.com/showthread.php?t=488959for a third party .NET solutions though.
不过,请查看http://www.extremeoptimization.com/Statistics/UsersGuide/ContinuousDistributions/NormalDistribution.aspx和http://www.vbforums.com/showthread.php?t=488959以获得第三方 .NET 解决方案。
回答by Jason DeFontes
Math.NET Iridiumalso claims to implement "non-uniform random generators (normal, poisson, binomial, ...)".
Math.NET Iridium还声称实现了“非均匀随机生成器(正常、泊松、二项式等)”。
回答by Drew Noakes
I created a request for such a feature on Microsoft Connect. If this is something you're looking for, please vote for it and increase its visibility.
我在 Microsoft Connect 上创建了对此类功能的请求。如果这是您正在寻找的东西,请为它投票并提高其知名度。
This feature is included in the Java SDK. Its implementation is available as part of the documentationand is easily ported to C# or other .NET languages.
此功能包含在 Java SDK 中。它的实现作为文档的一部分提供,并且可以轻松移植到 C# 或其他 .NET 语言。
If you're looking for pure speed, then the Zigorat Algorithmis generally recognised as the fastest approach.
如果您正在寻找纯粹的速度,那么Zigorat 算法通常被认为是最快的方法。
I'm not an expert on this topic though -- I came across the need for this while implementing a particle filterfor my RoboCup 3D simulated robotic soccer libraryand was surprised when this wasn't included in the framework.
不过,我不是这个主题的专家——我在为我的RoboCup 3D 模拟机器人足球库实现粒子过滤器时遇到了这个需求,并且当它没有包含在框架中时感到惊讶。
In the meanwhile, here's a wrapper for Random
that provides an efficient implementation of the Box Muller polar method:
同时,这里有一个包装器,Random
它提供了 Box Muller polar 方法的有效实现:
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;
}
}
回答by Aaron Stainback
You could try Infer.NET. It's not commercial licensed yet though. Here is there link
你可以试试 Infer.NET。不过,它还没有获得商业许可。这里有链接
It is a probabilistic framework for .NET developed my Microsoft research. They have .NET types for distributions of Bernoulli, Beta, Gamma, Gaussian, Poisson, and probably some more I left out.
它是我的 Microsoft 研究开发的 .NET 概率框架。他们有用于 Bernoulli、Beta、Gamma、Gaussian、Poisson 分布的 .NET 类型,可能还有一些我遗漏了。
It may accomplish what you want. Thanks.
它可能会完成你想要的。谢谢。
回答by Gordon Slysz
Math.NETprovides this functionality. Here's how:
Math.NET提供了此功能。就是这样:
double mean = 100;
double stdDev = 10;
MathNet.Numerics.Distributions.Normal normalDist = new Normal(mean, stdDev);
double randomGaussianValue= normalDist.Sample();
You can find documentation here: http://numerics.mathdotnet.com/api/MathNet.Numerics.Distributions/Normal.htm
您可以在此处找到文档:http: //numerics.mathdotnet.com/api/MathNet.Numerics.Distributions/Normal.htm
回答by Superbest
This question appears to have moved on top of Google for .NET Gaussian generation, so I figured I'd post an answer.
对于 .NET Gaussian 生成,这个问题似乎已经移到了 Google 之上,所以我想我会发布一个答案。
I've made some extension methods for the .NET Random class, including an implementation of the Box-Muller transform. Since they're extensions, so long as the project is included (or you reference the compiled DLL), you can still do
我为 .NET Random 类制作了一些扩展方法,包括 Box-Muller 变换的实现。由于它们是扩展,只要包含项目(或者您引用编译后的 DLL),您仍然可以执行
var r = new Random();
var x = r.NextGaussian();
Hope nobody minds the shameless plug.
希望没有人介意这个无耻的插件。
Sample histogram of results (a demo app for drawing this is included):
结果的示例直方图(包括用于绘制此图的演示应用程序):
回答by Hameer Abbasi
I'd like to expand upon @yoyoyoyosef's answer by making it even faster, and writing a wrapper class. The overhead incurred may not mean twice as fast, but I think it should be almosttwice as fast. It isn't thread-safe, though.
我想扩展@yoyoyoyosef 的答案,使其更快,并编写一个包装类。产生的开销可能并不意味着快两倍,但我认为它应该快两倍。但是,它不是线程安全的。
public class Gaussian
{
private bool _available;
private double _nextGauss;
private Random _rng;
public Gaussian()
{
_rng = new Random();
}
public double RandomGauss()
{
if (_available)
{
_available = false;
return _nextGauss;
}
double u1 = _rng.NextDouble();
double u2 = _rng.NextDouble();
double temp1 = Math.Sqrt(-2.0*Math.Log(u1));
double temp2 = 2.0*Math.PI*u2;
_nextGauss = temp1 * Math.Sin(temp2);
_available = true;
return temp1*Math.Cos(temp2);
}
public double RandomGauss(double mu, double sigma)
{
return mu + sigma*RandomGauss();
}
public double RandomGauss(double sigma)
{
return sigma*RandomGauss();
}
}
回答by Daniel Howard
This is my simple Box Muller inspired implementation. You can increase the resolution to fit your needs. Although this works great for me, this is a limited range approximation, so keep in mind the tails are closed and finite, but certainly you can expand them as needed.
这是我的简单 Box Muller 启发的实现。您可以增加分辨率以满足您的需要。虽然这对我很有用,但这是一个有限的范围近似值,所以请记住尾部是封闭的和有限的,但当然你可以根据需要扩展它们。
//
// by Dan
// islandTraderFX
// copyright 2015
// Siesta Key, FL
//
// 0.0 3231 ********************************
// 0.1 1981 *******************
// 0.2 1411 **************
// 0.3 1048 **********
// 0.4 810 ********
// 0.5 573 *****
// 0.6 464 ****
// 0.7 262 **
// 0.8 161 *
// 0.9 59
//Total: 10000
double g()
{
double res = 1000000;
return random.Next(0, (int)(res * random.NextDouble()) + 1) / res;
}
public static class RandomProvider
{
public static int seed = Environment.TickCount;
private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random>(() =>
new Random(Interlocked.Increment(ref seed))
);
public static Random GetThreadRandom()
{
return randomWrapper.Value;
}
}
回答by Neil
Expanding on Drew Noakes's answer, if you need better performance than Box-Muller (around 50-75% faster), Colin Green has shared an implementation of the Ziggurat algorithm in C#, which you can find here:
扩展 Drew Noakes 的答案,如果您需要比 Box-Muller 更好的性能(大约快 50-75%),Colin Green 在 C# 中分享了 Ziggurat 算法的实现,您可以在此处找到:
http://heliosphan.org/zigguratalgorithm/zigguratalgorithm.html
http://heliosphan.org/zigguratalgorithm/zigguratalgorithm.html
Ziggurat uses a lookup table to handle values that fall sufficiently far from the curve, which it will quickly accept or reject. Around 2.5% of the time, it has to do further calculations to determine which side of the curve a number is on.
Ziggurat 使用查找表来处理离曲线足够远的值,它会很快接受或拒绝这些值。大约 2.5% 的时间,它必须做进一步的计算来确定数字位于曲线的哪一侧。