This question has been asked before (stackoverflow) but the (accepted) answer is not satisfactory.
The following example saves and loads the state but depending on the number of generated values it works or it doesn't:
#include <fstream>
#include <iostream>
#include <random>
#include <cassert>
int main()
{
const int preN = 4;
const int middleN = 0;
// initialize randGen
std::mt19937 randGen1;
std::normal_distribution<double> distribution1;
// print some initial random numbers
for (int i=0;i<preN;++i)
std::cout << distribution1(randGen1)<<" ";
// save state
std::cout << std::endl << "Saving...\n";
{
std::ofstream fout("seed.dat");
fout << randGen1;
}
// maybe advance randGen1
for (int i=0;i<middleN;++i)
std::cout << distribution1(randGen1)<<" ";
// load saved state into randGen2
std::cout << std::endl << "Loading...\n";
std::ifstream fin("seed.dat");
std::mt19937 randGen2;
fin >> randGen2;
std::normal_distribution<double> distribution2;
// are both randGen equal?
assert(randGen1 == randGen2);
// print numbers from both generators
std::cout << "Generator1\tGenerator2\n";
std::cout << distribution1(randGen1) << "\t"
<< distribution2(randGen2) << "\n";
return 0;
}
With these parameters it works like expected. However, if I set preN=3
the output looks like:
0.13453 -0.146382 0.46065
Saving...
Loading...
Generator1 Generator2
-1.87138 0.163712
Why did the assert not apply? Now I set preN=3
and middleN=1
and the output is
0.13453 -0.146382 0.46065
Saving...
-1.87138
Loading...
Generator1 Generator2
0.163712 0.163712
If I set middleN
to anything larger than 1 the assert applies.
Can anyone explain what is going on? What am I doing wrong or not understanding?
Tested with GCC5.4.0 and CLANG3.8.0 on Linux
Pseudo Random Number Generator(PRNG) refers to an algorithm that uses mathematical formulas to produce sequences of random numbers. PRNGs generate a sequence of numbers approximating the properties of random numbers. A PRNG starts from an arbitrary starting state using a seed state.
How to Generate Random Numbers in C++ Within a Range. Similar to 1 and 10, you can generate random numbers within any range using the modulus operator. For instance, to generate numbers between 1 and 100, you can write int random = 1+ (rand() % 100).
int x = int(floor(rand() / (RAND_MAX + 1.0) * (high-low) + low));
The problem is not your random number generator's state. The problem is your distribution's state. Yes, distributions can have state too.
You can get the same values by resetting the normal distribution's state with reset
. Alternatively, you can preserve and reconstitute the distribution's state too, using <<
and >>
.
Thanks to the answer from Nicol Bolas above, I can add the corrected code below:
#include <fstream>
#include <iostream>
#include <random>
#include <cassert>
int main()
{
const int preN = 7;
const int middleN = 0;
// initialize another randGen
std::mt19937 randGen1;
std::normal_distribution<double> distribution1;
// print some initial random numbers
for (int i=0;i<preN;++i)
std::cout << distribution1(randGen1)<<" ";
// save state
std::cout << std::endl << "Saving...\n";
{
std::ofstream fout("seed.dat");
fout << randGen1;
fout.close();
std::ofstream fout2("distribution.dat");
fout2 << distribution1;
fout2.close();
}
// maybe advance randGen
for (int i=0;i<middleN;++i)
std::cout << distribution1(randGen1)<<" ";
// load saved state into randGen2
std::cout << std::endl << "Loading...\n";
std::mt19937 randGen2;
std::normal_distribution<double> distribution2;
{
std::ifstream fin("seed.dat");
fin >> randGen2;
fin.close();
std::ifstream fin2("distribution.dat");
fin2 >> distribution2;
fin2.close();
}
// are both randGen equal?
assert(randGen1 == randGen2);
assert(distribution1 == distribution2);
// print numbers from both generators
std::cout << "Generator1\tGenerator2\n";
std::cout << distribution1(randGen1) << "\t"
<< distribution2(randGen2) << "\n";
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With