5

这个问题之前已经被问过(stackoverflow),但(接受的)答案并不令人满意。

以下示例保存和加载状态,但取决于生成值的数量,它是否有效:

#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=3middleN=1输出是

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

如果我设置middleN为大于 1 的任何值,则断言适用。谁能解释发生了什么?我在做什么错或不理解?

在 Linux 上使用 GCC5.4.0 和 CLANG3.8.0 测试

4

3 回答 3

5

问题不在于您的随机数生成器的状态。问题是您的发行版的状态。是的,发行版也可以有状态。

您可以通过使用 重置正态分布的状态来获得相同的值reset。或者,您也可以使用和来保存和重构发行版的状态。<<>>

于 2017-02-21T21:23:17.033 回答
3

感谢上面Nicol Bolas的回答,我可以在下面添加更正的代码:

#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;
}    
于 2017-02-22T09:00:05.070 回答
0

以下是如何保存和恢复双浮点精度的随机数的种子。整数应该是相似的 - 使用 jrand48 而不是 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");  
}
于 2020-02-15T16:36:41.617 回答