Save and Load Random Number Generator State in C++11 - c++

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

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;
}

Here is how one can save and restore seed forrandom numbers of double float precision. It should be similar for integers - use jrand48 instead of erand48.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
unsigned short savedseed[3];
unsigned short currentseed[3];
double x;
/*-- initialize ramdom seed to whatever --*/
currentseed[0]= 23;
currentseed[1]= 45;
currentseed[2]= 67;
printf("\n");
/*-- generate three random numbers --*/
x = erand48(currentseed); printf("%g\n", x);
x = erand48(currentseed); printf("%g\n", x);
x = erand48(currentseed); printf("%g\n", x);
printf("\n");
/*-- save seed --*/
memcpy(savedseed, currentseed, 3*sizeof(unsigned short));
/*-- generate next three random numbers --*/
x = erand48(currentseed); printf("%g\n", x);
x = erand48(currentseed); printf("%g\n", x);
x = erand48(currentseed); printf("%g\n", x);
printf("\n", x);
/*-- restore seed --*/
memcpy(currentseed, savedseed, 3*sizeof(unsigned short));
/*-- generate the same three random numbers again --*/
x = erand48(currentseed); printf("%g\n", x);
x = erand48(currentseed); printf("%g\n", x);
x = erand48(currentseed); printf("%g\n", x);
printf("\n");
}

Related

Get the state (seed) of a distribution of random numbers

See the following program for g++.
#define seed1 0
#include <iostream>
#include <random>
int main()
{
double mean = 0.0;
double stddev = 1.0;
std::mt19937 generator1 (seed1);
std::normal_distribution<double> normal(mean, stddev);
std::cerr << "Normal: " << normal(generator1) << std::endl;
}
I want to get the state of generator1 (as a seed) and remove generator1 for later
instantiate again the distribution with the new seed and go on in the place I left I want to put this code in a function and call it to generate Gaussian points in the start state I want. And at the end of the function save the state as a seed.
save the state as a seed
That will never happen, the state of a generator is much more than its seed.
However, generators (and distributions, which you ignored in your question) do provide functionality to store and retrieve their state through the << / >> operators respectively on streams:
stream << generator1 << normal;
And later:
mt19937 generator;
stream >> generator;
normal_distribution<double> distribution;
stream >> distribution;
Let me also add, that generators and distributions are also constructible and copyable from itself, if there is a need to reuse it later.
#define seed1 0
#include <iostream>
#include <random>
int main()
{
double mean = 0.0;
double stddev = 1.0;
std::mt19937 generator1 (seed1);
std::normal_distribution<double> normal(mean, stddev);
std::cerr << "Normal: " << normal(generator1) << std::endl;
std::mt19937 generator2 = generator1;
std::normal_distribution<double> normal2 = normal;
std::cerr << "Normal: " << normal(generator1) << std::endl;
std::cerr << "Normal2: " << normal2(generator2) << std::endl;
// I want to get the state of generator1 (as a seed) and remove generator1 for later
//instantiate again the distribution with the new seed and go on in the place I left
// I want to put this code in a function and call it to generate Gaussian points in
// the start state I want. And at the end of the function save the state as a seed.
}
So last lines print the same result, as states were initialized to equal values.
There is one way you could try. This involves saving the original seed, and counting how many times the generator is called. To restore the state, seed with the original seed and then call std::mt19937::discard()
Example:
#define seed1 0
#include <cassert>
#include <iostream>
#include <random>
// spoof a generator that counts the number of calls
class my_mt19937 : public std::mt19937 {
public:
result_type operator()() {
++call_count_;
return std::mt19937::operator()();
}
void seed(result_type value = default_seed) {
original_seed_ = value;
std::mt19937::seed(value);
}
void discard(unsigned long long z) {
call_count_ += z;
std::mt19937::discard(z);
}
unsigned long long call_count() const noexcept { return call_count_; }
result_type original_seed() const noexcept { return original_seed_; }
private:
result_type original_seed_ = default_seed;
unsigned long long call_count_ = 0;
};
int main() {
double mean = 0.0;
double stddev = 1.0;
my_mt19937 gen1;
gen1.seed(seed1);
const size_t N = 10'000;
for (size_t i = 0; i < N; ++i) {
my_mt19937 gen2;
gen2.seed(gen1.original_seed());
gen2.discard(gen1.call_count());
if (gen2() != gen1()) {
std::cout << "failed for i = " << i << "\n";
return 1;
}
}
// this extneds to distribution objects that
// use the generators
std::normal_distribution<double> normal1;
std::normal_distribution<double> normal2;
for (size_t i = 0; i < N; ++i) {
my_mt19937 gen2;
gen2.seed(gen1.original_seed());
gen2.discard(gen1.call_count());
if (normal1(gen1) != normal2(gen2)) {
std::cout << "failed for i = " << i << "\n";
return 1;
}
}
std::cout << "Success! Tested " << N << " values\n";
return 0;
}
You can play further with the code on godbolt: https://godbolt.org/z/8j9onsezs

std::stof precision problems

I've got a .txt file with multiple x y and z float numbers and I'm getting line by line with std::getline(file, line).
My problem is: while I'm getting the values correctly for x, y and z in strings, their decimal places are being reduced and that's not what I want.
I want to know how to store the full value. From what I saw I can use std::setprecision() to correct this while printing, but I want to correct the stored values so I can use them.
What can I do? Are the numbers stored properly but not shown properly by my std::cout? Here's the code:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <regex>
int main()
{
std::string line;
std::ifstream input("input.txt");
std::vector<float> x;
std::vector<float> y;
std::vector<float> z;
std::regex reg("[,]+");
int line_count = 0;
if (input.is_open()) {
while (std::getline(input, line)) {
if (line_count > 0)
{
std::sregex_token_iterator iter(line.begin(), line.end(), reg, -1);
std::sregex_token_iterator end;
std::vector<std::string> tokens(iter, end);
std::cout << tokens[0] << std::endl;
x.push_back(std::stof(tokens[0]));
std::cout << x[line_count - 1] << std::endl;
y.push_back(std::stof(tokens[1]));
z.push_back(std::stof(tokens[2]));
}
line_count++;
}
}
/*for (size_t i = 0; i < x.size(); i++)
{
std::cout << x[i] << " " << y[i] << " " << z[i] << std::endl;
}*/
}
The .txt file is as follows:
x,y,z
-0.015869140625,0.896728515625,-0.103515625
-0.00634765625,0.8935546875,-0.147216796875
-0.00634765625,0.8935546875,-0.147216796875
-0.02197265625,0.9326171875,-0.10400390625
-0.02197265625,0.9326171875,-0.10400390625
-0.078369140625,0.944580078125,-0.126220703125
-0.078369140625,0.944580078125,-0.126220703125
-0.047119140625,0.979248046875,-0.114990234375
-0.047119140625,0.979248046875,-0.114990234375
0.022216796875,1.0068359375,-0.096435546875
-0.009033203125,1.02685546875,-0.078369140625
-0.009033203125,1.02685546875,-0.078369140625
-0.052490234375,1.033935546875,-0.114501953125
Double and float do not have that precision.
You can use The GNU Multiple Precision Arithmetic Library class mpf_class.

why c++ std accumulate is always return 0

I am trying to use c++ to sum 3 integers from the input, but I keep get 0. Please help thx.
vector<int> x;
x.reserve(3);
cin >> x[0] >> x[1] >> x[2];
int sum = std::accumulate(x.begin(), x.end(), 0);
cout << sum << endl;
return 0;
1
2
3
0
vector::reserve(size_type n) will request a change in the capacity of the vector, not the size. You can use the resize function, or even better the constructor.
int main()
{
std::vector<int> x(3,0); //set the size to 3 and fill with zeros.
std::cin >> x[0] >> x[1] >> x[2];
int sum = std::accumulate(x.begin(), x.end(), 0);
std::cout << sum << std::endl;
}
You can read this answer here for the differences between reserve vs resize.
Fill your vector first with something if not you will probably get undefined
vector<int> x(3,0);
use c++ to sum 3 integers from the input
why accumulate always return 0
This answer uses push_back(), and does not need to know how many integers are input, as the vector will auto expand; In this way it sidesteps the issues of std::vector that were defeating your code.
Consider that, because a "how many int" might be submited is seldom fixed you are more likely to want to count how many input "on the fly". So perhaps use a loop, cin to a local var, then x.push_back( a_local_var), and repeat until some condition (maybe eof(), or local var == -1, etc.) x.size() is your counter.
Here is a functioning example, using command line vars and eof() (and a vector and accumulate).
// Note: compile with -std=c++17 for the using comma list
#include <iostream>
using std::cout, std::cerr, std::endl, std::hex, std::dec, std::cin, std::flush; // c++17
#include <vector>
using std::vector;
#include <string>
using std::string;
#include <sstream>
using std::stringstream;
#include <numeric>
using std::accumulate;
#include <cassert>
class T951_t // ctor and dtor compiler provided defaults
{
public:
int operator()(int argc, char* argv[]) { return exec(argc, argv); } // functor entry
private:
stringstream ssIn; // to simulate user input
int exec(int argc, char* argv[])
{
int retVal = initTest(argc, argv); // transfer command line strings into ssIn
if(retVal != 0) return retVal;
// ------------------------------------------------------------
// simulate unknown quantity of ints
vector<int> x;
do {
int localInt = 0;
ssIn >> localInt;
if(!ssIn.good()) // was transfer ok?
{ // no
if (ssIn.eof()) break; // but we tolerate eof
// else err and exit
cerr << "\n !ssIn.good() failure after int value "
<< x.back() << endl;
assert(0); // harsh - user typo stops test
}
x.push_back(localInt); // yes transfer is ok, put int into vector
//cout << "\n " << localInt; // diagnostic
} while(true);
showResults(x);
return 0;
}
// this test uses a stringstream (ssIn) to deliver input to the app
// ssIn is initialized from the command line arguments
int initTest(int argc, char* argv[])
{
if (argc < 2) {
cerr << "\n integer input required" << endl;
return -1;
}
// test init
for (int i=1; i < argc; ++i) {
// cout << "\n " << argv[i]; // diagnostic
ssIn << argv[i] << " "; // user text into stream
}
cout << endl;
return 0;
}
// display size and contents of vector x
void showResults(vector<int> x)
{
cout << "\n x.size(): " << x.size() << endl;
int sum = std::accumulate(x.begin(), x.end(), 0);
for (auto i : x)
cout << " " << i;
cout << endl;
cout << "\n sums to: " << sum << '\n' << endl;
}
}; // class T951_t
int main(int argc, char* argv[]) { return T951_t()(argc, argv); } // call functor
Tests:
./dumy951 1 2 3 55 12345678900 <-- fail after 55 because last int too big
./dumy951 1 2 3 y 55 12345678900 <-- fail after int value 3 (invalid int)
./dumy951 1 2 3 4 5 6 7 8 9 10 <-- success, result is 55

How to create an array of normal distributed random number generators in c++?

I need a series of normally distributed random numbers, with different mean and variance, I know how to create one series with a particular mean and variance but can I have like an array of generators?
like for 1 series we have
#include <random>
#include <iostream>
using namespace std;
int main()
{
random_device rd;
mt19937 gen(rd());
normal_distribution<double> d(0.0, 1.0);
for (int i = 0; i < 5000; i++)
cout << " " << d(gen) << "\n";
return 0;
}
and this gives me a series of normally distributed random numbers, and i know i can create another d with another mean and variance for another series but is there any way to have a lot of such normal_distribution d together in an array so that i can choose a particular generator by simply choosing an element in the array.
I have tried a version where
#include <random>
#include <iostream>
using namespace std;
int main()
{
random_device rd;
mt19937 gen(rd());
normal_distribution<double> d(0.0, 1.0),d2(0.0,1.0);
normal_distribution<double> D[]={d,d2};
for (int i = 0; i < 5000; i++)
cout << " " << D[0](gen) << "\n";
system("pause");
return 0;
}
but I want to initialize it directly with the array like D0 some thing like that so that i can put it in a loop
Sure you can
#include <iostream>
#include <vector>
#include <random>
int main() {
std::vector<std::normal_distribution<double>> D{
std::normal_distribution<double>{0.0, 1.0 },
std::normal_distribution<double>{0.0, 2.0 } };
std::random_device rd;
std::mt19937 gen(rd());
std::cout << D[0](gen) << "\n";
std::cout << D[1](gen) << "\n";
return 0;
}
As you know C++ provide a functions for random numbers and we can also create and initialize array as given below. I hope it will helpful if not comment below.
const int nrolls=10000; // number of experiments
const int nstars=100; // maximum number of stars to distribute
std::default_random_engine generator;
std::normal_distribution<double> distribution(5.0,2.0);
int p[10]={};
for (int i=0; i<nrolls; ++i) {
double number = distribution(generator);
if ((number>=0.0)&&(number<10.0)) ++p[int(number)];
}
std::cout << "normal_distribution (5.0,2.0):" << std::endl;
for (int i=0; i<10; ++i) {
std::cout << i << "-" << (i+1) << ": ";
std::cout << std::string(p[i]*nstars/nrolls,'*') << std::endl;
}

How to print a number with precision given by the user in c++

How to print a number with precision given by the user. And how to print precision after decimal point up to 100 digits.
Suppose A,B,C be three numbers and take the value of three numbers from the user and I have to print the answer of A/B ( A divided by B ) to C floating points.
If A=22, B=7 , C=25, that means I have to print the result of 22/7 to 25 floating points.
3.1428571428571428571428571 , this is the answer of 22/7 , 25 digits after decimal point.
As many have pointed out, use std::fixed and std::setprecision
#include <iostream>
#include <iomanip>
int main()
{
float x = 22.0/7.0;
std::cout << std::fixed << std::setprecision(25) << x;
return 0;
}
But when you run this you will see the output is
3.1428570747375488281250000 when it should be
3.1428571428571428571428571. What gives?
Well, floats can only hold so much before having to give up and say, "Best I can do, mate." Rumour has it, this point is about 7 digits. Based on a quick count that looks about right.
So what say we try a double. They're twice the size!
#include <iostream>
#include <iomanip>
int main()
{
double x = 22.0/7.0;
std::cout << std::fixed << std::setprecision(25) << x;
return 0;
}
gives us
3.1428571428571427937015414. Still not
3.1428571428571428571428571, but closer. What have we got that's bigger than double? Just tried long double. No dice on my computer. Looks like we're going to have to go looking for a good high precision floating point library.
Bummer. Well, there is one in Boost. I someday expect to see boost::kitchen_sink.
To print a float with a precision "n" you should write :
printf("%.nf"); // like printf("%.3f")
there you are a c++ full code
#include <stdio.h>
#include <stdlib.h>
#include <strstream>
#include <iostream>
int main()
{
// print a float with precision '4'
printf("%.4f",10.125f);
// print a float with precision 'n'
char * buffer = new char[100];
int n;
std::strstream ss; // like cout but outputs to a string buffer
ss<<"%.";
std::cout<<"Enter precision : ";
std::cin>>n;
ss<<n<<"f";
printf(ss.str(),10,125); // ss.str() to get buffer content
delete[] buffer;
return 0;
}
but very simply you still can write
std::cout << std::setprecision(n) << float_var;
EDIT :
you can do you own division ! i mean you can simulate the devision of the processor and get whatever precision you want , till inifinity ! , there you are the amazing code that i wrote for my friend one time for fun :
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <chrono>
int main()
{
std::cout.sync_with_stdio(false); // accelerate output
register int x,y;
char opp;
std::cout<<"Enter x/y : ";
std::cin>>x>>opp>>y;
std::cout<<"deviding "<<x<<" by "<<y<<std::endl;
register int precision;
std::cout<<"Enter precision : ";
std::cin>>precision;
register int precision_counter = 0;
typedef std::chrono::high_resolution_clock Time;
typedef std::chrono::nanoseconds ms;
typedef std::chrono::duration<float> fsec;
auto t0 = Time::now();
std::cout <<"Result = ";
std::cout<<x/y;
// check if there will be a float point result to print a point
if(x<y || x%y != 0)
{
std::cout<<".";
x%=y; // remove what we printed
register int counter = 0;
// print digts that are after the float point
while (precision_counter<precision )
{
x*=10;
while (x>=y)
{
x-= y;
counter++;
}
std::cout<<counter;
counter = 0;
precision_counter++;
}
/*
optimized loop :
while (precision_counter<precision )
{
x*=10;
std::cout<<x/y;
x%=y;
precision_counter++;
}
**/
}
auto t1 = Time::now();
fsec fs = t1 - t0;
std::cout<<"\n";
ms d = std::chrono::duration_cast<ms>(fs);
std::cout << fs.count() << "s\n";
std::cout << d.count() << " nanosecond\n";
std::cout<<std::endl;
system("pause");
return 0;
}
#include <iostream>
#include <string>
#include <sstream>
std::string f(int A, int B, int C){//A: numerator, B:denominator, C:digits after decimal point
std::stringstream ss;
int count = 0;
if(A < 0){
A = -A;
++count;
}
if(B < 0){
B = -B;
++count;
}
if(count == 1)
ss << '-';
ss << A / B << '.';
A %= B;
A *= 10;
count = C;
while(count--){
ss << A / B;
A %= B;
A *= 10;
}
return ss.str();
}
int main(void){
std::cout << f(22, 7, 25) << std::endl;
return 0;
}