Mersenne twister seed as

2.3k views Asked by At

I would like to maintain the random number generator state as a member variable, so every object generated from this class will have its one. It is necessary, that everytime an object is generated the seed gets changed too.

I did the following thing, namely changing the seed through the object's constructer. The seeding I did with time(NULL) but this is not accurate enough, since the the objects get created way faster than within a second, haha.

#include <iostream>
#include <cmath>
#include<random>
#include<chrono>
#include <ctime>


class Test{
public:
    Test();
    std::mt19937 rng;
    double randomNumber(double min, double max);

};
Test::Test(){
    rng.seed(time(NULL));
}

double Test::randomNumber(double min, double max){
    std::uniform_real_distribution<double> uniformDistribution(min, max);
    return uniformDistribution(rng);
}

int main(){
    Test a;
    Sleep(1000*1);
    Test b;

    for (int i = 0; i < 10; i++){
        std::cout << "Random number a: " << a.randomNumber(0, 10) << "\tRandom number b: " << b.randomNumber(0, 10) << std::endl;

    }

}

I am struggling with the method described in [Seeding rand() for a C++ class by bames53.

Including this piece

std::mt19937 eng{ std::chrono::high_resolution_clock::now().time_since_epoch().count() };

into the class declarations yields the following error:

Error: no instance of constructor "std::merseene_twister_engine<_Ty,_Wx, many more things> argument types are (std::chrono::system_clock::rep)

Now I do not exactly know where the error comes from and how to achieve my problem. Please keep in mind I am more or less an c++ newby. Thank you!

1

There are 1 answers

7
shuttle87 On

Given your description you could initialize the RNG once then pass it as a reference to the Test class:

class Test{
public:
    Test(std::mt19937& rng): m_rng(rng){
    }

    std::mt19937& m_rng;
    double randomNumber(double min, double max){
        std::uniform_real_distribution<double> uniformDistribution(min, max);
        return uniformDistribution(m_rng);
    }

};

std::mt19937 rng{std::chrono::high_resolution_clock::now().time_since_epoch().count()};
Test a(rng);

Because this particular RNG has a very long period you can instantiate it once then draw values from it across all your classes that need the random number generation.

Sample usage:

std::mt19937 rng{std::chrono::high_resolution_clock::now().time_since_epoch().count()};
Test a(rng);
Test b(rng);
for(int i=0; i<10; ++i){
    std::cout<< "a: " << a.randomNumber(0.0,1.0) << "b: " << b.randomNumber(5.0,6.0) << std::endl;
}

Here's this code in action: http://ideone.com/Lzyp22