我有一段简短的代码,运行Mersenne Twister PRNG,效果很好:
std::random_device randDev;
std::mt19937 twister(randDev());
std::uniform_int_distribution<int> dist(0,99);
for (int i = 0; i < 10; i++) {
std::cout << dist(twister) << std::endl;
}
输出十个随机数。但是,如果我将完全相同的代码放入函数中:
#include <random>
int getRand(const int& A, const int& B) {
std::random_device randDev;
std::mt19937 twister(randDev());
std::uniform_int_distribution<int> dist(A,B);
return dist(twister);
}
int main() {
for (int i = 0; i < 10; i++) {
std::cout << getRand(0,99) << std::endl;
}
return 0;
}
输出相同的数字十次。我刚刚开始使用C ++,所以我不知道是什么导致这个或如何解决这个问题。
编辑:问题在于std :: random_device。它可能是Eclipse C ++ IDE(Luna版本)或MinGW 4.8.1中的错误,但无论出于何种原因,随机数总是相同的。我相信时间(0)将是适合我用途的种子。
编辑2 :考虑到TC的建议以及时间(0)仍然导致10个相同数字的事实,这里到目前为止的最终代码。我知道rand()很糟糕但是有效。
#include <iostream>
#include <random>
std::mt19937 twister(rand());
int getRand(const int& A, const int& B) {
std::uniform_int_distribution<int> dist(A,B);
return dist(twister);
}
int main() {
for (int i = 0; i < 10; i++) {
std::cout << getRand(0,99) << std::endl;
}
return 0;
}
答案 0 :(得分:3)
问题是每次调用函数时都会创建一个全新的种子,随机数生成器和分布。这不是使用这些类的正确方法。
使用随机数生成器的正确方法是创建一次并将其用于整个程序所需的次数(或至少相当长的时间)。以单一功能的形式:
#include <random>
#include <iostream>
int getRand(const int& A, const int& B) {
static std::random_device randDev;
static std::mt19937 twister(randDev());
static std::uniform_int_distribution<int> dist;
dist.param(std::uniform_int_distribution<int>::param_type(A, B));
return dist(twister);
}
int main() {
for (int i = 0; i < 10; i++) {
std::cout << getRand(0, 99) << std::endl;
}
return 0;
}
静态变量在第一次调用函数时初始化,并重新用于所有后续调用。
答案 1 :(得分:0)
您使用什么编译器和操作系统? Visual Studio 2012(不确定2013年)没有真正的std :: random_device实现,这意味着每次都使用相同的值进行初始化 - 所以在这种情况下,每次都会使用相同的种子初始化mersenne twister,因此结果相同。
顺便说一下,似乎问了同样的问题:
Why do I get the same sequence for every run with std::random_device with mingw gcc4.8.1?
显然,Windows上的GCC4.8也将std :: random_device实现为伪随机。