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)
随机生成器的重点是保持算法的状态,以便基于特定的随机种子生成可重复的数字伪随机序列。
随机设备的重点是为随机发生器提供随机种子。
如果您尝试为每个随机值播种新的生成器,那么您将不再行使随机生成器算法提供的随机性。相反,您使生成器偏向于依赖随机设备本身的随机性。
因此,不建议使用示例#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
循环内部有点没有意义。当然,通过编译器优化,并不会真正造成伤害,并且有时为了清楚起见,有时最好将分发保持在使用位置附近。
如果我需要为多个不相关的东西生成随机值,是否需要创建不同的生成器或可以保持相同?
如果需要,欢迎使用多个生成器生成不相关的随机序列-这实际上是它们的主要吸引人之一。如果在生成其他序列时不使用伪随机算法的生成器(最值得注意的是从序列中提取数字时,则保留该伪随机算法的随机性保证)。
这对于重现性也很有用:例如,当您实际上有一个特定的种子值(而不是从随机设备中提取它)时,将该种子用于一个特定序列将提供可重复的结果,而与同时使用任何其他序列无关时间。
另一个主要好处是,通过使用单独的生成器,您可以获得与其他对象相同的线程安全保证。换句话说,这意味着如果您要同时生成多个伪随机序列,则可以在没有锁的情况下这样做,前提是每个线程都在单独的生成器上运行。