Use of random in C++

Joh*_*mph 4 c++ random

Are these pieces of code equivalent in terms of "randomness" ?

1)

std::vector<int> counts(20);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 19);

for (int i = 0; i < 10000; ++i) {
    ++counts[dis(gen)];
}
Run Code Online (Sandbox Code Playgroud)

2)

std::vector<int> counts(20);
std::random_device rd;
std::mt19937 gen(rd());

for (int i = 0; i < 10000; ++i) {
    std::uniform_int_distribution<> dis(0, 19);
    ++counts[dis(gen)];
}
Run Code Online (Sandbox Code Playgroud)

3)

std::vector<int> counts(20);
std::random_device rd;

for (int i = 0; i < 10000; ++i) {
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 19);
    ++counts[dis(gen)];
}
Run Code Online (Sandbox Code Playgroud)

4)

std::vector<int> counts(20);

for (int i = 0; i < 10000; ++i) {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 19);
    ++counts[dis(gen)];
}
Run Code Online (Sandbox Code Playgroud)

In the documentation of std::random_device, it is says that multiple std::random_device object may generate the same number sequence so the code 4 is bad, isn't it ?

And for the other codes ?

If I need to generate random values for multiple stuffs unrelated, must I need to create differents generators or can I keep the same ? :

1)

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> disInt(0, 10);
std::uniform_float_distribution<> disFloat(0, 1.0f);

// Use for one stuff
disInt(gen);

// Use same gen for another unrelated stuff
disFloat(gen);
Run Code Online (Sandbox Code Playgroud)

2)

std::random_device rd1, rd2;
std::mt19937 gen1(rd1()), gen2(rd2());
std::uniform_int_distribution<> disInt(0, 10);

// Use for one stuff
disInt(gen1);

// Use another gen for another unrelated stuff
disFloat(gen2);
Run Code Online (Sandbox Code Playgroud)

pad*_*ddy 6

随机生成器的重点是保持算法的状态,以便基于特定的随机种子生成可重复的数字伪随机序列。

随机设备的重点是为随机发生器提供随机种子

如果您尝试为每个随机值播种新的生成器,那么您将不再行使随机生成器算法提供的随机性。相反,您使生成器偏向于依赖随机设备本身的随机性。

因此,建议使用示例#3和#4 。

生成随机序列的正确方法是示例1:

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 19);

for (int i = 0; i < 10000; ++i) {
    int foo = dis(gen);
}
Run Code Online (Sandbox Code Playgroud)

例#2也是正确的,但构造uniform_int_distribution循环内部有点没有意义。当然,通过编译器优化,并不会真正造成伤害,并且有时为了清楚起见,有时最好将分发保持在使用位置附近。

如果我需要为多个不相关的东西生成随机值,是否需要创建不同的生成器或可以保持相同?

如果需要,欢迎使用多个生成器生成不相关的随机序列-这实际上是它们的主要吸引人之一。如果在生成其他序列时不使用伪随机算法的生成器(最值得注意的是从序列中提取数字时,则保留该伪随机算法的随机性保证)。

这对于重现性也很有用:例如,当您实际上有一个特定的种子值(而不是从随机设备中提取它)时,将该种子用于一个特定序列将提供可重复的结果,而与同时使用任何其他序列无关时间。

另一个主要好处是,通过使用单独的生成器,您可以获得与其他对象相同的线程安全保证。换句话说,这意味着如果您要同时生成多个伪随机序列,则可以在没有锁的情况下这样做,前提是每个线程都在单独的生成器上运行。