如何从C++<random>获得一致的行为

How to get consistent behavior from C++ <random>

本文关键字:random C++ lt gt      更新时间:2023-10-16

我遇到了一个问题,如果我从C++ <random>库中重新设定随机数生成器的种子,我有时会从序列中获得即将到来的值作为第一个样本。在第一个样本之后,我得到了一个可重复的序列。它似乎有一个模式,但我不能完全弄清楚它是什么。

最小示例:

#include <iostream>
#include <random>
using namespace std;
int main(){
        mt19937 engine {1};
        normal_distribution<float> nd {0, 1};
        for (int i=0; i<10; i++){
                for (int j=0; j<=i; j++) {
                        cout << nd(engine) << endl;
                }
                cout << endl;
                engine.seed(1);
        }
        return 0;
}

使用 g++ (Ubuntu 7.3.0-27ubuntu1~18.04( 编译,在 WSL Ubuntu 18.04.2 上没有任何标志。

我得到以下输出:

0.3064
0.156066
0.3064
0.156066
0.3064
0.156066
0.3064
0.156066
-0.424386
-0.56804
0.3064
0.156066
-0.424386
-0.56804
-0.204547
-0.806289
0.3064
0.156066
-0.424386
-0.56804
-0.204547
-0.806289
0.3064
0.156066
-0.424386
-0.56804
-0.204547
-0.806289
0.3064
0.156066
-0.424386
-0.56804
-0.204547
-0.806289
-0.428738
-1.20004
0.3064
0.156066
-0.424386
-0.56804
-0.204547
-0.806289
-0.428738
-1.20004
1.30547
-1.18775
0.3064
0.156066
-0.424386
-0.56804
-0.204547
-0.806289
-0.428738
-1.20004
1.30547

我希望 0.3064 始终是我得到的第一个值。我可以通过在重新播种后烧掉样品来解决此问题,但我没有看到何时需要这样做的明确模式。有谁知道我为什么会这样做?是否有我应该使用的编译器标志?

您忘记重置发行版的状态。播种发动机后呼叫nd.reset();

原始代码在此处复制,并带有修复程序:

#include <iostream>
#include <random>
using namespace std;
int main(){
        mt19937 engine {1};
        normal_distribution<float> nd {0, 1};
        for (int i=0; i<10; i++){
                for (int j=0; j<=i; j++) {
                        cout << nd(engine) << endl;
                }
                cout << endl;
                engine.seed(1);
                nd.reset();
        }
        return 0;
}

带输出的实时示例