Сохранение и загрузка состояния генератора случайных чисел в C ++ 11

Этот вопрос задавался ранее (переполнение стека) но (принятый) ответ не является удовлетворительным.

В следующем примере сохраняется и загружается состояние, но в зависимости от количества сгенерированных значений оно работает или не работает:

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

}

С этими параметрами все работает как положено. Однако, если я установлю preN=3 вывод выглядит так:

0.13453 -0.146382 0.46065
Saving...

Loading...
Generator1  Generator2
-1.87138    0.163712

Почему утверждение не применяется? Теперь я установил preN=3 а также middleN=1 и вывод

0.13453 -0.146382 0.46065
Saving...
-1.87138
Loading...
Generator1  Generator2
0.163712    0.163712

Если я установлю middleN к чему-то большему, чем 1, применяется утверждение.
Кто-нибудь может объяснить, что происходит? Что я делаю не так или не понимаю?

Протестировано с GCC5.4.0 и CLANG3.8.0 в Linux

3

Решение

Проблема не в состоянии вашего генератора случайных чисел. Проблема ваша дистрибутивных государство. Да, у дистрибутивов тоже может быть состояние.

Вы можете получить те же значения, сбросив состояние нормального распределения с помощью reset, Кроме того, вы можете сохранить и восстановить состояние распределения тоже, используя << а также >>,

4

Другие решения

Благодаря ответу от Николь Болас выше, я могу добавить исправленный код ниже:

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

По вопросам рекламы [email protected]