0

I created a function that is suppose to generate a set of normal random numbers from 0 to 1. Although, it seems that each time I run the function the output is the same. I am not sure what is wrong.

Here is the code:

MatrixXd generateGaussianNoise(int n, int m){
    MatrixXd M(n,m);
    normal_distribution<double> nd(0.0, 1.0);
    random_device rd;
    mt19937 gen(rd());
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            M(i,j) = nd(gen);
        }
    }
    return M;
}

The output when n = 4 and m = 1 is

0.414089
0.225568
0.413464
 2.53933

I used the Eigen library for this, I am just wondering why each time I run it produces the same numbers.

  • 1
    There's no such thing as "normal numbers from 0 to 1". The normal distribution has an infinite support. – pjs Feb 04 '17 at 18:20
  • Side note: you can avoid the two for loops using [NullaryExpr](https://eigen.tuxfamily.org/dox/classEigen_1_1DenseBase.html#a5a75198edac1ad62205648445ee30d34). – ggael Feb 04 '17 at 22:10

1 Answers1

3

From: http://en.cppreference.com/w/cpp/numeric/random/random_device

std::random_device may be implemented in terms of an implementation-defined pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation. In this case each std::random_device object may generate the same number sequence.

Thus, I think you should look into what library stack you are actually using here, and what's known about random_device in your specific implementation.

I realize that this then might in fact be a duplicate of "Why do I get the same sequence for every run with std::random_device with mingw gcc4.8.1?".

Furthermore, it at least used to be that initializating a new mt19937 instance would be kind of expensive. Thus, you have performance reasons in addition to quality of randomness to not re-initalize both your random_device and mt19937 instance for every function call. I would go for some kind of singleton here, unless you have very clear constraints (building in a library, unclear concurrency) that would make that an unuistable choice.

Community
  • 1
  • 1
cnettel
  • 1,024
  • 5
  • 7
  • Could you suggest a modified funtion that I should consider making then? –  Feb 04 '17 at 18:31
  • A crude way would be to turn `rd` and `gen` static. Note that it will still give identical results if you rerun the full program, as opposed to multiple calls to function over the course of a single execution of the program. – cnettel Feb 04 '17 at 18:36
  • I am a bit new to C++ so some of the terminology you mention I can follow but I am not sure how to implement what you suggested. –  Feb 04 '17 at 18:40
  • Sorry, simply put the word `static` before `random_device` as well as `mt19937`. In effect, this means that the variables are permanent, rather than being re-initialized at each function invocation. – cnettel Feb 04 '17 at 18:42
  • Do you call the function multiple times within the same program, or do you run the same program multiple times? Like I wrote before, if you want separate results each time you run the program, you will have to find some other seed than the current implementation of random_device. – cnettel Feb 04 '17 at 18:49
  • I just run the .cpp file again (using ecclipse) –  Feb 04 '17 at 18:54
  • Then you'll need to seed using something else. You might remove the usage of `rd` entirely, and instead seed your mt19937 instance on time(0), i.e. `static mt19937 gen(time(0))`. Seeding on time has its own pros and cons, but at least it will vary unless you launch it several times within a second. – cnettel Feb 04 '17 at 18:56
  • Ok, ill give that a try essentially what I was trying to do more or less is create a C++ function for the Matlab function randn() –  Feb 04 '17 at 18:59