Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Random numbers in C++11: is there a simple way to seed the generator in one place of the code, then use it in different functions?

Tags:

c++

random

c++11

Before C++11, I used rand() from <cstdlib> and it was very simple to choose to seed (or not) the generator in the main() function (for example), then use in libraryA random numbers generated by a function somewhere in libraryB. The code looked like this:

LibraryB (generates random numbers, old-fashioned way):

#include <cstdlib> // rand, RAND_MAX
double GetRandDoubleBetween0And1() {
   return ((double)rand()) / ((double)RAND_MAX);
}

Main program:

#include <cstdlib> // srand
#include <ctime> // time, clock
int main() {
   bool iWantToSeed = true; // or false,
                            // decide HERE, applies everywhere!
   if(iWantToSeed){
      srand((unsigned)time(0) + (unsigned int)clock());
   }
   // (...)
}

LibraryA (uses random numbers from LibraryB, generated according to the seed given in main()):

#include "../folderOfLibraryB/Utils_random.h" // GetRandDoubleBetween0And1
void UseSomeRandomness(){
   for(int i = 0; i < 1000000; i++){
      double nb = GetRandDoubleBetween0And1();
      // (...)
   }
}

Easy, right?

Now I would like to update GetRandDoubleBetween0And1() using the C++11 standards available via #include <random>. I have already read and seen the examples here and there, but I don't see how to adapt it to my three modules. Surely, seeding the engine inside GetRandDoubleBetween0And1() is not the right thing to do...

Do you think I will have to pass the seeded engine from main() to UseSomeRandomness() in LibraryA, then from UseSomeRandomness() to GetRandDoubleBetween0And1() in LibraryB? Or is there a simpler way?

like image 650
Georg Avatar asked Jul 02 '17 15:07

Georg


People also ask

What is the seed of a random number generator?

When you use statistical software to generate random numbers, you usually have an option to specify a random number seed. A seed is a positive integer that initializes a random-number generator (technically, a pseudorandom-number generator). A seed enables you to create reproducible streams of random numbers.

Which function is used to seed a new random number sequence?

srand() uses its argument seed as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand(). If srand() is not called, the rand() seed is set as if srand(1) was called at program start. Any other value for seed sets the generator to a different starting point.

What function is used to seed the random number generator in C++?

The rand() function in C++ is used to generate random numbers; it will generate the same number every time we run the program. In order to seed the rand() function, srand(unsigned int seed) is used. The srand() function sets the initial point for generating the pseudo-random numbers.


2 Answers

Do you think I will have to pass the seeded engine from main() to UseSomeRandomness() in LibraryA, then from UseSomeRandomness() to GetRandDoubleBetween0And1() in LibraryB?

Yes.

You instantiate the generator once, then pass a reference or pointer to it into whatever contexts want to use it.

This is just like dealing with any other resource.

like image 150
Lightness Races in Orbit Avatar answered Sep 27 '22 23:09

Lightness Races in Orbit


You can do something like this:

#include <random>

inline double GetRandDoubleBetween0And1() {
    thread_local static std::mt19937 gen{std::random_device{}()};
    thread_local static std::uniform_real_distribution pick{0.0, 1.0};
    return pick(gen);
}

Being inline means you can put it in a header file and the compiler will create only one copy of the static objects which it will resolve at link time. However if you use it in a dynamic library you will get different copies. In that case you can put this function in its own library and link it to each program that uses the function.

The thread_local ensures thread safety (one random generator per thread) and being static they are only initialized once.

like image 27
Galik Avatar answered Sep 27 '22 22:09

Galik