【问题标题】:Why do I get the same random numbers when i properly seeded my generator?当我正确地播种生成器时,为什么会得到相同的随机数?
【发布时间】:2021-02-28 17:14:01
【问题描述】:

我正在尝试制作一个迷你彩票模拟器。我想生成 8 个随机数,最小为 1,最大为 20。我将这些生成的数字存储在 Lottery 对象中。我有一个 LotteryManager 类,我可以在其中决定要生成这些彩票的次数。但我总是得到相同的随机数。我为生成器播种,所以我不明白它有什么问题。任何帮助表示赞赏!

这是我的彩票课:

class Lottery
{
private:
    vector<int> lotteryA;
    int lotteryB;
public:
    Lottery();

    vector<int> getLotteryA() const;
    int getLotteryB() const;

    void generateLotteryA();
    void generateLotteryB();
    void printLottery() const;
};

这是管理它的类:

class LotteryManager
{
private:
    unsigned int quanity = 0;
    map<unsigned int, Lottery> lotteries;
public:
    LotteryManager();
    LotteryManager(unsigned int q);

    unsigned int getQuanity() const;
    void setQuanity(unsigned int value);

    void generateLotteries();
    void printLotteries() const;
};

这是我的主要代码:

LotteryManager* lm = new LotteryManager(100);
    lm->generateLotteries();
    lm->printLotteries();

LotteryManager类中的生成和打印函数:

void LotteryManager::generateLotteries()
{
    for(unsigned int i = 0; i < getQuanity(); ++i)
    {
        Lottery l;
        l.generateLotteryA();
        l.generateLotteryB();
        lotteries.insert(make_pair(i, l));
        l.printLottery();
    }
}

void LotteryManager::printLotteries() const
{
    cout << "Lotteries:" << endl;
    for(auto current : lotteries)
    {
        cout << current.first << ".: ";
        current.second.printLottery();
    }
}

Lottery 类中的生成函数: (生成A和B只是不同的字段,因为游戏旨在模仿名为Putto的游戏,您需要从A字段的20中猜测8个数字,在B字段的4中猜测1)

void Lottery::generateLotteryA()
{
    random_device rn_d;
    mt19937 rng(rn_d());
    uniform_int_distribution<int> dist(1, 20);
    for(unsigned int i = 0; i < 8; ++i)
    {
        lotteryA.push_back(dist(rng));
    }
}

void Lottery::generateLotteryB()
{
    srand(time(0));
    lotteryB = (rand() % 20) + 1;
}

提前致谢!

【问题讨论】:

  • "...当我正确地为生成器播种时?" 您没有正确地为生成器播种,因为您一直在重新播种。尝试只播种一次,让它成为一个单例。
  • @yazan 原则上问题是一样的,但我不会提出关于&lt;random&gt; 的问题重复关于rand() 的问题,这有点倒退
  • @idclev463035818 绝对是。另一方面,这一定是骗子吧?我看了看,发现了很多 rand 目标,但没有这个:p
  • 这能回答你的问题吗? srand() — why call it only once?

标签: c++ random random-seed


【解决方案1】:

Lottery::generateLotteryA 中,您声明了一个随机引擎和随机设备。每次调用此函数时,引擎都会使用相同的随机设备播种,因此您可以获得相同的结果。


每次使用不同的random_devices 调用rn_d() 会产生不同的值似乎是合理的。但是,这不是必需的,正如reference 中提到的:

...每个 std::random_device 对象可以生成相同的数列。

在实践中,大多数实现生成不同的值,所以这不是一个真正的问题。你甚至可以认为它是标准库中的一个缺陷,因为它没有做出这个保证。但是,按照目前的规定,您可以看到正在生成的相同值。


最简单的解决方法是将引擎设为static,这样它只会在第一次调用函数时被播种:

void Lottery::generateLotteryA()
{
    // ...
    static mt19937 rng(rn_d());
    // ...
}

【讨论】:

  • OP 显示的代码不会生成符合mt19937 要求的随机数,但random_device rn_d; rn_d(); 不应该仍然返回随机数(除了它是random_device 的实现坏了)?
  • @t.niese 好问题。由于我不清楚的原因,调用此设备的结果是实现定义的,并且每次都允许产生相同的序列。见第二句here
  • 我在发送评论的那一刻看到了您的编辑。
  • @t.niese 啊,好的,所以编辑现在已经足够清楚了吗?
  • 唯一一个错误的random_device(我知道)的实现是MinGW。从 GCC 9.2 开始已修复。
猜你喜欢
  • 2012-09-01
  • 1970-01-01
  • 2023-03-18
  • 2014-01-05
  • 1970-01-01
  • 2016-08-19
  • 1970-01-01
  • 1970-01-01
  • 2015-03-14
相关资源
最近更新 更多