24

I would like to create a function that accepts Double mean, Double deviation and returns a random number with a normal distribution.

Example: if I pass in 5.00 as the mean and 2.00 as the deviation, 68% of the time I will get a number between 3.00 and 7.00

My statistics is a little weak…. Anyone have an idea how I should approach this? My implementation will be C# 2.0 but feel free to answer in your language of choice as long as the math functions are standard.

I think this might actually be what I am looking for. Any help converting this to code?

Thanks in advance for your help.

Community
  • 1
  • 1
J.Hendrix
  • 2,199
  • 4
  • 20
  • 26
  • Thanks everyone who has posted so far. You are pointing me in the right direction. I did not realize this was such a complex task. I was pretty sure someone would cough up a 4 liner in no time. – J.Hendrix Oct 26 '09 at 18:54
  • http://stackoverflow.com/questions/218060/random-gaussian-variables – yoyoyoyosef Sep 05 '13 at 13:40
  • Using the [MedallionRandom](https://www.nuget.org/packages/MedallionRandom) package, you can do this with `mean + (random.NextGaussian() * deviation)` – ChaseMedallion Oct 08 '16 at 17:24

9 Answers9

21

See this CodeProject article: Simple Random Number Generation. The code is very short, and it generates samples from uniform, normal, and exponential distributions.

John D. Cook
  • 29,517
  • 10
  • 67
  • 94
12

You might be interested in Math.NET, specifically the Numerics package.

Caveat: The numerics package targets .NET 3.5. You may need to use the Iridium package if you are targeting an earlier version...

Restore the Data Dumps
  • 38,967
  • 12
  • 96
  • 122
  • Looking at the feature at http://www.mathdotnet.com/doc/IridiumFeatures.ashx now... Not quite sure which function I want. Maybe one of the Continuous Probability Distributions? I might just have to download the source and pour over the code tonight. – J.Hendrix Oct 26 '09 at 18:23
  • 1
    You want to use MathNet.Numerics.Distributions, and do something like that, which will draw from a Normal with mean 5.0 and sigma 0.68: var mu = 5.00; var sigma = 0.68; var normal = new NormalDistribution(mu, sigma); var draw = normal.NextDouble(); – Mathias Oct 26 '09 at 20:57
8

Here is some C that returns two values (rand1 and rand2), just because the algorithm efficiently does so. It is the polar form of the Box-Muller transform.

void RandVal (double mean1, double sigma1, double *rand1, double mean2, double sigma2, double *rand2)
{
double u1, u2, v1, v2, s, z1, z2;

do {
    u1 = Random (0., 1.);  // a uniform random number from 0 to 1
    u2 = Random (0., 1.);
    v1 = 2.*u1 - 1.;
    v2 = 2.*u2 - 1.;
    s = v1*v1 + v2*v2;
} while (s > 1. || s==0.); 

z1 = sqrt (-2.*log(s)/s)*v1;
z2 = sqrt (-2.*log(s)/s)*v2;
*rand1 = (z1*sigma1 + mean1);
*rand2 = (z2*sigma2 + mean2);
return;

}

Ian W
  • 503
  • 4
  • 15
  • 1
    It would be helpful if you named your variables something other than "u", "v", etc., for example, mean and sigma are very helpful. – devlord Oct 23 '10 at 01:10
  • 4
    The variables u, v, z, and s are used to maintain consistency with the customary mathematical notation used in the Box-Muller transform. – Ian W Dec 06 '12 at 17:19
  • 4
    As a tutor I can attest that it would have been helpful for most people if the customary mathematical notations themselves had been labeled more descriptively. – Alex Jansen May 16 '13 at 03:10
5

This library is pretty good also:

.NET random number generators and distributions

redcalx
  • 8,177
  • 4
  • 56
  • 105
2

Sorry I don't have any code for you but I can point you to some algorithms on Wikipedia. The algorithm you choose I guess depends on how accurate you want it and how fast it needs to be.

shoelzer
  • 10,648
  • 2
  • 28
  • 49
Martin Sherburn
  • 5,958
  • 2
  • 23
  • 17
  • +1 This looks good too. How do I create the "two independent random numbers U and V uniformly distributed on (0, 1]"? Sorry... I told you my stats are weak. – J.Hendrix Oct 26 '09 at 18:46
  • In C# you would use the "Random" class (http://msdn.microsoft.com/en-us/library/system.random.aspx). Specifically the method NextDouble returns a uniformly distributed number in the range of 0 to 1. Uniformly distributed just means that you have an equal chance of getting any of the numbers in the range, there is no bias towards any specific number. – Martin Sherburn Oct 27 '09 at 08:53
1

For those referencing this question, an easy solution might be:

Random rand = new Random();
double normRand  = alglib.invnormaldistribution(rand.NextDouble())

scale by mu and sigma as needed.
The alglib library is available at www.alglib.net

Ace
  • 11
  • 1
1

MathNet

from second top answer

    public static double GenerateRandomVariant(double mean,double deviation,System.Random rand=null, int factor=1)
    {

        rand = rand ?? new Random();
        double randNormal=(MathNet.Numerics.Distributions.Normal.Sample(rand, mean , deviation));
        return factor * randNormal;

    }

Box-Mueller Transform

from top answer via link (twice as fast?)

by u/yoyoyoyosef Random Gaussian Variables

    public static double GenerateRandomVariant(double mean, double deviation, System.Random rand=null, int factor = 1)
    {
        rand = rand ?? new Random();
        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 +  deviation * randStdNormal); //random normal(mean,stdDev^2)
        return randNormal * factor;
    }
Declan Taylor
  • 408
  • 6
  • 8
0

The MetaNumerics library, also .NET, will calculate a normal distribution (and just about anything else from statistics), super quickly. Have a look at the Feature's page for more details. The Codeplex page is here: http://metanumerics.codeplex.com/.

Justin R.
  • 23,435
  • 23
  • 108
  • 157
0

I know this post is a little old but I would like to share a small project I created yesterday. I think the easier way is to use C++ 11 and create a .dll in Managed C++. There's a link to the source and a zip containing the dll already compiled.

And the code I made :

// NormalDistributionRandom.h
#include <random>

#pragma once

using namespace System;

namespace NormalDistribution 
{

    class _NormalDistributionRandom
    {
        std::default_random_engine engine;
        std::normal_distribution<double> distribution;

    public:
        _NormalDistributionRandom(double mean, double deviation) : distribution(mean, deviation)
        {
        }

        double Next()
        {
            return distribution(engine);
        }
    };

    public ref class NormalDistributionRandom
    {
    private:

        void* Distribution;

    public:

        NormalDistributionRandom( double mean, double deviation)
        {
            Distribution = new _NormalDistributionRandom(mean, deviation);
        }

        double Next()
        {
            return ((_NormalDistributionRandom*)Distribution)->Next();
        }
        ~NormalDistributionRandom()
        {
            this->!NormalDistributionRandom();
        }
    protected:
        !NormalDistributionRandom()
        {
            if (Distribution != nullptr)
            {
                delete (_NormalDistributionRandom*)Distribution;
                Distribution = nullptr;
            }
        }
    };

}
pascx64
  • 904
  • 16
  • 31