【问题标题】:c++ std::normal_distribution gives inconsistent random numbers when restoring from filec++ std::normal_distribution 从文件恢复时给出不一致的随机数
【发布时间】:2015-12-02 10:56:40
【问题描述】:

我正在编写蒙特卡罗模拟并实施检查点。我想获得完全相同的结果,无论我是从检查点重新启动模拟还是继续超越它。但是,我遇到了std::normal_distribution 的一些奇怪行为:

我使用std::mt19937 rng; 作为 RNG 并将其播种为固定数字。我通过std::uniform_real_distribution uniform;std::normal_distribution normal; 绘制了一定数量的随机数。然后,我将 rng 的状态写入ofstream os

os << rng << endl;
os << <some other stuff>...

紧接着,我又画了几个数字:

os << uniform(rng) << endl;
os << uniform(rng) << endl;
os << uniform(rng) << endl;
os << normal(rng) << endl;
os << normal(rng) << endl;
os << normal(rng) << endl;
os << uniform(rng) << endl;
os << uniform(rng) << endl;
os << uniform(rng) << endl;

我得到以下输出:

0.727133
0.215537
0.516879
-2.12532
0.314652
1.78136
0.511111
0.83119
0.637067

如果我从检查点重新启动,即从 ifstream is 初始化生成器:

is >> rng;
is >> <some other stuff>...

并绘制相同的 9 个随机数(3 个统一,3 个正常,3 个统一),我得到:

0.727133
0.215537
0.516879
0.314652
1.78136
1.28201
0.637067
0.298175
0.802607

你看,统一的数字是相同的,直到一个正常的数字被绘制出来,之后 rng 的状态就不同了。使用gdb 确认这一点。

【问题讨论】:

  • 这可能只是您的代码中的一个错误吗?你能做一个独立的、可重现的例子吗(例如使用字符串流进行序列化)?
  • @KerrekSB 我认为他没有意识到normal 具有内部状态。
  • 确实,我没有。我想知道 Box-Mueller 方法成对生成正常随机数是可以理解的。 (并不是说 Box-Mueller 一定是实现的,但我想原理是一样的。)谢谢,伙计!

标签: c++ c++11 random


【解决方案1】:

查看0.637067 在两个输出中的位置。您会注意到,与未恢复时相比,正态分布在恢复时必须从 rng 中提取更多的数字。那是因为你检查点时它有熵。

您必须保存或重置normal 的状态。作为检查点过程的一部分,我建议在normal 上调用reset

【讨论】:

  • 我最终只是存储了分布而不是调用reset。检查点是根据挂钟时间完成的,因此当目标是获得确定性结果(用于调试)时,它不应该扰乱随机数的序列。感谢您的快速回复,我开始怀疑我对这个问题的理智。
猜你喜欢
  • 2017-04-12
  • 2019-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多