Random Gaussian Variables

Is there a class in the .NET standard library that gives me the ability to create random variables that follow the Gaussian distribution?

+84
c # random normal-distribution gaussian
Oct. 20 '08 at 11:06
source share
12 answers

Jarrett’s suggestion of using Box-Muller transforms is useful for a quick and dirty solution. Simple implementation:

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) 
+138
Oct 20 '08 at 14:16
source share

This question seems to have moved on top of the Google generation for .NET Gaussian, so I decided that I would post the answer.

I made several extension methods for the .NET Random class , including an implementation of the Box-Muller transform. Since they are extensions, if the project is included (or you are referring to a compiled DLL), you can still do

 var r = new Random(); var x = r.NextGaussian(); 

Hope no one misses the shameless plugin.

Example histogram of results (demo drawing application included):

enter image description here

+42
Mar 21 '13 at 19:30
source share

http://mathworld.wolfram.com/Box-MullerTransformation.html

Using two random variables, you can generate random values ​​along the Gaussian distribution. This is not a difficult task.

+12
Oct 20 '08 at 12:11
source share

Math.NET provides this functionality. Here's how:

 double mean = 100; double stdDev = 10; MathNet.Numerics.Distributions.Normal normalDist = new Normal(mean, stdDev); double randomGaussianValue= normalDist.Sample(); 

Here you can find the documentation: http://numerics.mathdotnet.com/api/MathNet.Numerics.Distributions/Normal.htm

+7
Oct 16 '12 at 10:11
source share

I created a request for such a feature in Microsoft Connect. If this is what you are looking for, vote for it and increase its visibility.

https://connect.microsoft.com/VisualStudio/feedback/details/634346/guassian-normal-distribution-random-numbers

This feature is included in the Java SDK. Its implementation is available as part of the documentation and is easily ported to C # or other .NET languages.

If you are looking for pure speed, then the particle filter algorithm for my RoboCup 3D imitated a robotic football library and was surprised when it was not included in the framework.




At the same time, here is a wrapper for Random that provides an efficient implementation of the polar Box Muller method:

 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; } } 
+6
Jan 04 2018-11-11T00:
source share

Math.NET Iridium also claims to implement "uneven random generators (normal, poisson, binomial, ...)."

+5
Oct 20 '08 at 21:34
source share

I would like to extend the answer to @yoyoyoyosef, making it even faster and writing a wrapper class. Overhead losses may not mean twice as fast, but I think it should be almost twice as fast. However, it is not thread safe.

 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(); } } 
+2
Aug 27 '13 at 8:26
source share

This is my simple Box Muller insert. You can increase the resolution to suit your needs. Although this works fine for me, this is a limited range approximation, so keep in mind that the tails are closed and finite, but of course you can expand them as needed.

  // // 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; } } 
+1
Aug 20 '15 at 4:27
source share

Turning around on Drew Noakes, if you need better performance than Box-Muller (about 50-75% faster), Colin Green shared an implementation of the Ziggurat algorithm in C #, which you can find here:

http://heliosphan.org/zigguratalgorithm/zigguratalgorithm.html

Ziggurat uses a lookup table to process values ​​that are far enough from the curve that it quickly accepts or rejects. At approximately 2.5% of the time, he must perform further calculations to determine which side of the curve the number is on.

+1
Jan 28 '17 at 4:15
source share

Here's another quick and dirty solution for generating random variables with normal propagation . He draws some random point (x, y) and checks if this point is under the curve of your probability density function, otherwise it repeats.

Bonus: you can generate random variables for any other distribution (for example, an exponential distribution or a Poisson distribution ) by simply replacing the density function.

  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 * σ * σ)); } 

Important: select the interval y and the parameters σ and μ so that the function curve is not cut off in it with maximum / minimum points (for example, with x = average). Think of the x and y intervals as the bounding box into which the curve should fit.

+1
Mar 13 '17 at 17:23
source share

You can try Infer.NET. However, this is not a commercial license. Here is the link

This is the probabilistic framework for .NET that developed my research on Microsoft. They have .NET types for the Bernoulli, Beta, Gamma, Gauss, Poisson distributions, and possibly some more that I forgot about.

He can accomplish what you want. Thank.

0
Jan 15 2018-12-12T00:
source share

I do not think so. And I really hope not, because the structure is already quite bloated, without such specialized functionality filling it even more.

Take a look at http://www.extremeoptimization.com/Statistics/UsersGuide/ContinuousDistributions/NormalDistribution.aspx and http://www.vbforums.com/showthread.php?t=488959 for third-party .NET solutions.

-one
Oct 20 '08 at 11:11
source share



All Articles