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

Prior to C ++ 11, I used rand() from <cstdlib> , and it was very simple to select the seeds (or not) of the generator in the main() function (for example), and then use random numbers generated by the function in libraryA somewhere in library B. 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); } 

The 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 specified 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 through #include <random> . I already read and saw examples here and there , but I don’t know. Look how to adapt it to my three modules. Of course, sowing the engine inside GetRandDoubleBetween0And1() is not what you need to do ...

Do you think I will have to pass the seed engine from main() to UseSomeRandomness() to LibraryA, and then from UseSomeRandomness() to GetRandDoubleBetween0And1() to LibraryB? Or is there an easier way?

+5
source share
3 answers

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

Yes.

You instantiate the generator once, then pass the link or pointer to it in any contexts that you want to use.

This is similar to working with any other resource.

+5
source

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 that you can put it in the header file, and the compiler will only create one copy of the static objects that it will solve during the link. However, if you use it in a dynamic library, you will get different copies. In this case, you can put this function in your own library and link it to every program that uses this function.

thread_local provides thread safety (one random generator per thread) and is static, they only initialize once.

+4
source

My β€œrandom” library provides a high convenient wrapper around C ++ 11 random classes. You can do almost anything with a simple get method.

In your use case, you can use an automatic serialized random_static wrapper with a static API.

Examples:

 #include "effolkronium/random.hpp" using Random = effolkronium::random_static; auto Func( ) { return Random::get(-10, 10 ) } auto Func2( ) { return Random::get(-10, 10 ) } int main( ) { // Seed static internal engine Random::seed( MySuperSeed ); } 

This is the only library for headers only.

Check out the github page: https://github.com/effolkronium/random

0
source

Source: https://habr.com/ru/post/1269414/


All Articles