只有 std::mt19937 的实例重复 c++11 中的值
Only instance of std::mt19937 repeats values in c++11
在程序中,经常在不同的class中生成随机数。所以我想创建一个 class 即 returns 生成器的单个实例 std::mt19937。我还考虑到某些编译器无法使用 std::random_device(为此,请检查熵的值)。我创建了一个 class 单例。
#include <iostream>
#include <random>
#include <chrono>
class RandomGenerator
{
public:
static RandomGenerator& Instance() {
static RandomGenerator s;
return s;
}
std::mt19937 get();
private:
RandomGenerator();
~RandomGenerator() {}
RandomGenerator(RandomGenerator const&) = delete;
RandomGenerator& operator= (RandomGenerator const&) = delete;
std::mt19937 mt;
};
RandomGenerator::RandomGenerator() {
std::random_device rd;
if (rd.entropy() != 0) {
mt.seed(rd());
}
else {
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
mt.seed(seed);
}
}
std::mt19937 RandomGenerator::get() {
return mt;
}
int main() {
std::mt19937 &mt = RandomGenerator::Instance().get();
std::uniform_real_distribution<double> dist(0.0, 1.0);
for (std::size_t i = 0; i < 5; i++)
std::cout << dist(mt) << "\n";
std::cout << "\n";
std::mt19937 &mt2 = RandomGenerator::Instance().get();
std::uniform_real_distribution<double> dist2(0.0, 1.0);
for (std::size_t i = 0; i < 5; i++)
std::cout << dist2(mt2) << "\n";
return 0;
}
但是当我从 class 生成器 std::mt19937 出来时,随机数开始重复。如何避免?
0.389459
0.68052
0.508421
0.0758856
0.0137491
0.389459
0.68052
0.508421
0.0758856
0.0137491
P.S。有没有比时间更好的初始化生成器的方法?
解决方案
在以下编译器下进行了测试:Visual Studio、MinGW、DevC++。
#include <iostream>
#include <random>
#include <chrono>
class RandomGenerator
{
public:
static RandomGenerator& Instance() {
static RandomGenerator s;
return s;
}
std::mt19937 & get();
private:
RandomGenerator();
~RandomGenerator() {}
RandomGenerator(RandomGenerator const&) = delete;
RandomGenerator& operator= (RandomGenerator const&) = delete;
std::mt19937 mt;
};
RandomGenerator::RandomGenerator() {
std::random_device rd;
if (rd.entropy() != 0) {
mt.seed(rd());
}
else {
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
mt.seed(seed);
}
}
std::mt19937 & RandomGenerator::get() {
return mt;
}
int main() {
std::mt19937 &mt = RandomGenerator::Instance().get();
std::uniform_real_distribution<double> dist(0.0, 1.0);
for (std::size_t i = 0; i < 5; i++)
std::cout << dist(mt) << "\n";
std::cout << "\n";
std::mt19937 &mt2 = RandomGenerator::Instance().get();
std::uniform_real_distribution<double> dist2(0.0, 1.0);
for (std::size_t i = 0; i < 5; i++)
std::cout << dist2(mt2) << "\n";
return 0;
}
std::mt19937 get();
returns 一份。每次调用 get()
时,都会复制引擎的初始状态。 mt19937
是一个伪随机引擎,每个状态产生一个预定的序列。如果两个实例的状态相同,它们将产生相同的序列。使函数 return 成为引用,以便单例实例的状态随着每个生成的新数字而更新。
std::mt19937 & RandomGenerator::get() {
return mt;
}
在程序中,经常在不同的class中生成随机数。所以我想创建一个 class 即 returns 生成器的单个实例 std::mt19937。我还考虑到某些编译器无法使用 std::random_device(为此,请检查熵的值)。我创建了一个 class 单例。
#include <iostream>
#include <random>
#include <chrono>
class RandomGenerator
{
public:
static RandomGenerator& Instance() {
static RandomGenerator s;
return s;
}
std::mt19937 get();
private:
RandomGenerator();
~RandomGenerator() {}
RandomGenerator(RandomGenerator const&) = delete;
RandomGenerator& operator= (RandomGenerator const&) = delete;
std::mt19937 mt;
};
RandomGenerator::RandomGenerator() {
std::random_device rd;
if (rd.entropy() != 0) {
mt.seed(rd());
}
else {
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
mt.seed(seed);
}
}
std::mt19937 RandomGenerator::get() {
return mt;
}
int main() {
std::mt19937 &mt = RandomGenerator::Instance().get();
std::uniform_real_distribution<double> dist(0.0, 1.0);
for (std::size_t i = 0; i < 5; i++)
std::cout << dist(mt) << "\n";
std::cout << "\n";
std::mt19937 &mt2 = RandomGenerator::Instance().get();
std::uniform_real_distribution<double> dist2(0.0, 1.0);
for (std::size_t i = 0; i < 5; i++)
std::cout << dist2(mt2) << "\n";
return 0;
}
但是当我从 class 生成器 std::mt19937 出来时,随机数开始重复。如何避免?
0.389459
0.68052
0.508421
0.0758856
0.0137491
0.389459
0.68052
0.508421
0.0758856
0.0137491
P.S。有没有比时间更好的初始化生成器的方法?
解决方案
在以下编译器下进行了测试:Visual Studio、MinGW、DevC++。
#include <iostream>
#include <random>
#include <chrono>
class RandomGenerator
{
public:
static RandomGenerator& Instance() {
static RandomGenerator s;
return s;
}
std::mt19937 & get();
private:
RandomGenerator();
~RandomGenerator() {}
RandomGenerator(RandomGenerator const&) = delete;
RandomGenerator& operator= (RandomGenerator const&) = delete;
std::mt19937 mt;
};
RandomGenerator::RandomGenerator() {
std::random_device rd;
if (rd.entropy() != 0) {
mt.seed(rd());
}
else {
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
mt.seed(seed);
}
}
std::mt19937 & RandomGenerator::get() {
return mt;
}
int main() {
std::mt19937 &mt = RandomGenerator::Instance().get();
std::uniform_real_distribution<double> dist(0.0, 1.0);
for (std::size_t i = 0; i < 5; i++)
std::cout << dist(mt) << "\n";
std::cout << "\n";
std::mt19937 &mt2 = RandomGenerator::Instance().get();
std::uniform_real_distribution<double> dist2(0.0, 1.0);
for (std::size_t i = 0; i < 5; i++)
std::cout << dist2(mt2) << "\n";
return 0;
}
std::mt19937 get();
returns 一份。每次调用 get()
时,都会复制引擎的初始状态。 mt19937
是一个伪随机引擎,每个状态产生一个预定的序列。如果两个实例的状态相同,它们将产生相同的序列。使函数 return 成为引用,以便单例实例的状态随着每个生成的新数字而更新。
std::mt19937 & RandomGenerator::get() {
return mt;
}