icurays1
icurays1

Reputation: 360

Generating random double vectors with <random> and a function

I've written the following function to generate a random vector of doubles:

void getrands(vector<double> *x)
{
  int N=(*x).size();
  uniform_real_distribution<double> unif(0.0,1.0);
  mt19937 re(time(NULL));
  auto generator = bind(unif,re);
  generate_n((*x).begin(),N,generator);
}

In my main() program, if I try to call this function on several vectors (say I want to generate 10 random vectors) I end up with all my vectors having the same random numbers in them, because not enough time has elapsed to get a good re-seed. What is a better way to do this? Should I create a random array then convert it to vectors? I'm used to matlab where I can just call X=rand(n,m)...

Thanks!

Upvotes: 3

Views: 1183

Answers (2)

Praetorian
Praetorian

Reputation: 109119

A better way would be to seed your random number generator using std::random_device.

mt19937 re(std::random_device{}());

And you should probably pass the RNG as an argument to the function, rather than create a new instance every iteration.

Also, be aware that std::bind copies its arguments, so you may want to wrap the RNG in std::ref before passing it as an argument to bind.


I'd rewrite your function as

template<typename Generator>
void getrands(vector<double>& x, Generator& gen, unsigned num)
{
  generate_n(std::back_inserter(x), num, std::ref(gen));
}

And call it as

uniform_real_distribution<double> unif(0.0,1.0);
mt19937 re(std::random_device{}());
auto generator = bind(unif, std::ref(re));

vector<double> vs;

getrands(vs, generator, 10);

This allows you to reuse the same RNG, you don't need to set the vector to the correct size before calling the function and you can add values to the vector if needed.

Live demo

Upvotes: 6

Siyuan Ren
Siyuan Ren

Reputation: 7844

You should move out the definition for the std::mt19937 into the global scope so that it gets initialized only once. Random number generation is one of the rare cases where a global variable makes more sense. Besides, the best practice for seeding is to use std::random_device rather than the current time.

Upvotes: 1

Related Questions