Talonus11
Talonus11

Reputation: 33

How do i create a c++ random normal distribution that works in a separate method?

I've managed to get a working normal distribution in my main() function using the following code:

default_random_engine generator(time(0));
normal_distribution<double> distribution(6.0,5.0);


for (int i = 0; i < 51; i++)
{
    cout << "#" << i << "= " << distribution(generator);
}

This will happily print out 50 values that follow a distribution with a mean of 6.0 and an average of 5.0 for example:

#0= 0.999998
#1= 3.43872
#2= 6.83918
#3= -3.81324
#4= 16.0962
#5= 1.26236

However, as soon as i move the same code into a method and call said method to return individual values that will populate the output, it only returns the same value over again:

double normalGenerator(double mean, double stdDev)
{
    default_random_engine generator(time(0));
    normal_distribution<double> distribution(mean,stdDev);
    return distribution(generator);
}

(in main()):

for (int i = 0; i < 51; i++)
    {
        cout << "#" << i << "= " << distribution(generator);
        cout << " " << normalGenerator(6.0,5.0) << endl;
    }

Output:

#0= 5.49136 5.49136
#1= 7.6902 5.49136
#2= 14.4971 5.49136
#3= 11.946 5.49136
#4= 4.37424 5.49136
#5= 9.91711 5.49136

The first column is the original code, the second is the method-called value.

I assume my issue is based on the

default_random_engine generator(time(0));
normal_distribution<double> distribution(6.0,5.0);

lines being in the method, but my understanding of how they work isn't great and i haven't found any good beginner-level documentation to help me understand it.

Upvotes: 1

Views: 2790

Answers (1)

Rerito
Rerito

Reputation: 6086

Let's just dissect your normalGenerator method:

double normalGenerator(double mean, double stdDev)
{
    default_random_engine generator(time(0)); // We initialize a generator
    normal_distribution<double> distribution(mean,stdDev); // And a distribution
    return distribution(generator); // distribution operator() always take the same generator with the same state
}

Pseudo Random Generators are deterministic, so if you keep on supplying a generator in the same state to your distribution object it will keep on outputing the same value over and over again. However, each time you use the generator, its internal state will change and thus, when generating other values, you'll get other outputs.

A quick change and you're good to go:

default_random_engine generator(time(0));
normal_distribution<double> distribution(mean,stdDev);

Becomes:

static default_random_engine generator(time(0));
normal_distribution<double> distribution(mean,stdDev);

As @PeterBecker pointed out, you should also try to keep using the same distribution object. This way you can benefit from potential caching of variable generations.

However this cannot be achieved by making the object static because you could need other normal distributions with other parameters (mean and variance).

Upvotes: 4

Related Questions