当前位置: 首页 > 知识库问答 >
问题:

只有std::mt19937的实例重复c 11中的值

叶桐
2023-03-14

在程序中,经常在不同的类中生成随机数。所以我想创建一个返回生成器std::mt19937的单个实例的类。我还考虑到一些编译器不使用std::random_device(为此,请检查熵的值)。我创建了一个类单例。

#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;
}

但是等我出了类generator std::mt19937,随机数就开始重复了。如何避免?

0.389459
0.68052
0.508421
0.0758856
0.0137491

0.389459
0.68052
0.508421
0.0758856
0.0137491

P、 有没有比时间更好的方法来初始化生成器?

溶液

在以下编译器下测试了这个: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;
}

共有1个答案

伍溪叠
2023-03-14

std::mt19937 get();返回副本。每次调用 get() 时,您都会复制引擎的初始状态。mt19937 是一个伪随机引擎,每个状态产生一个预定的序列。如果两个实例的状态相同,它们将生成相同的序列。使函数返回引用,以便使用生成的每个新数字更新单一实例的状态。

std::mt19937 & RandomGenerator::get() {
    return mt;
}
 类似资料:
  • C11标准6.5.2.3中给出了以下示例 以下不是有效片段(因为union类型在函数f中不可见): 为什么联合类型对函数f可见有关系? 我在翻阅有关的部分时,看不出其中有甚么不容许这样做的地方。

  • 问题内容: 这是我写的三个类: Tester类的main方法的输出为: 为什么sx返回0而不是1?由于不是Rectangle变量的当前实例,并且该类也声明了相同的实例变量,或者Rectangle类中的变量没有像对getX()一样覆盖Shape类中的先前公共x变量。矩形类中的方法因此返回1? 同样作为一般规则,超类仅在其子类中也声明了其子类方法时才可以访问其子类的实现?这是因为编译器会看到“ Sha

  • 在文件r.java中。我删除了它,但由于它是自动生成的,所以它只是再次添加它,并且无法再编译一次。我得到的错误是变量GradientColor_fontVariationSettings已在类Styleable中定义。 编辑:我找到了文件并删除了引用,但问题仍然存在。有人有什么想法吗

  • 亲爱的堆栈溢出用户。 我试图找到的优点,以及为什么我应该使用它而不是函子或函数指针。可悲的是,我没有找到一个令人满意的答案。 因此,如果您能告诉我< code>std::function的优点是什么,以及我应该在什么时候使用它,我将非常感激。希望我的问题也能帮助到别人。

  • 我有以下课程 我在下面的代码中使用 由此产生的行为对我来说是可以理解的。在第一次调用中,构造一个小部件,然后调用移动构造函数,并在临时小部件上调用析构函数。 第二个调用也执行相同的操作,除了调用move赋值运算符而不是move构造函数。离开main方法,析构函数在<code>c<code>上调用。 现在是有趣的部分: 如果我省略了对< code>std::move的调用,第一种情况会停止工作,只导