Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::default_random_engine generates the same values even with changing seed?

I'm trying to implement a class that will serve as sort of a wrapper for the random library so I can use its objects and functions in (I think) a more intuitive way elsewhere in my code.

In my header I have something like this:

class RandomDevice{
private:
    unsigned long rand_seed;
    default_random_engine engine;
public:
    RandomDevice(unsigned long n);
    int randInt(int min, int max);};

And then in the .cpp file I implement those two functions (constructor and randInt) like so:

RandomDevice::RandomDevice(unsigned long n){
    rand_seed = n;
    default_random_engine engine;
    engine.seed(n);
}

int RandomDevice::randInt(int min, int max){
    uniform_int_distribution<int> distribution(min, max);
    return distribution(engine);
}

Finally, in my main.cpp I test these functions like this:

int main(){
    unsigned long seed = 1;
    RandomDevice my_rand(seed);

    cout << "random integer: " << my_rand.randInt(0, 10) << endl;
}

The problem is, no matter what I set the seed to in main.cpp, I always get the same values for my random numbers (not just randInt, I have other distributions as well). I've also tried setting seed to time(NULL) but the same problem occurs.

I'm really scratching my head at this one. Thanks!

like image 609
InvisibleAndre Avatar asked Feb 22 '15 00:02

InvisibleAndre


3 Answers

Try using std::chrono to feed the seed in each iteration or in every call. I think seeding time moments would give best randomness, since each time moment is a unique seed without any repetitions. I would do the following:

#include <chrono> 
...
default_random_engine engine; // or any other engine
engine.seed(std::chrono::system_clock::now().time_since_epoch().count());
like image 144
Pavlos Sakoglou Avatar answered Nov 05 '22 06:11

Pavlos Sakoglou


default_random_engine engine;
engine.seed(n);

This is seeding the local engine, which is destroyed at the end of the constructor, not the class member engine, which ends up being default constructed.

Use the member initializer list instead:

RandomDevice::RandomDevice(unsigned long n) : rand_seed(n), engine(n){ }
like image 14
T.C. Avatar answered Nov 05 '22 06:11

T.C.


In your construction function, the new created local engine masks your private class memeber engine .
Just delete 2nd line of your RandomDevice::RandomDevice(), you will be fine.

Like this.

RandomDevice::RandomDevice(unsigned long n){
    rand_seed = n;
    engine.seed(n);
}

or using member intialize list as @T.C. said,

RandomDevice::RandomDevice(unsigned long n): rand_seed(n), engine(n) { }
like image 1
Xin Cheng Avatar answered Nov 05 '22 04:11

Xin Cheng