【问题标题】:Why am I getting the same answer from random numbers?为什么我从随机数中得到相同的答案?
【发布时间】:2021-01-06 00:09:48
【问题描述】:

您好,我编写了一个 C++ 程序,它使用 rand() 函数处理随机数,结果很奇怪。实际代码中还有很多内容,但代码的基本思想类似于:

int main()
{
    srand(time(NULL));
    priority_queue<long long int> pQueueInts;
    const int TRIALS = 1000000;
    for (int i = 0; i < TRIALS; i++)
    {
        long long int holder = randomNumber();
        pQueueInts.push(holder);
    }

    cout << pQueueInts.top();
    for (int i = 0; i < TRIALS / 2; i++)
        pQueueInts.pop();

    cout << pQueueInts.top();

    for (int i = 0; i < (TRIALS / 2) - 1; i++)
        pQueueInts.pop();

    cout << pQueueInts.top();
}

long long int randomNumber()
{
    bool found = false;
    long long int counter = 0;
    while (found == false)
    {
        int roll = rand() % 500;
        if (roll == 1)
        {
            roll = rand() % 500;
            if (roll == 2)
                found = true;
        }
        counter++;
    }

    found = false;

    while (found == false)
    {
        int roll = rand() % 100;
        if (roll == 3)
        {
            roll = rand() % 250;
            if (roll == 4)
                found = true;
        }
        counter++;
    }

    found = false;

    while (found == false)
    {
        int roll = rand() % 530;
        if (roll == 5)
        {
            roll = rand() % 400;
            if (roll == 6)
                found = true;
        }
        counter++;
    }

    return counter / 3;
}

它运行并执行得很好,但是如果我说进行 1M 次试验并从中找到最大的计数器结果,然后我退出程序并再次运行它,但是经过 1000 次试验,您会期望该样本中最大的计数器更小比 1M 试验,但它的数字完全相同。如果我随后将样本更改为 10M,我可能会得到一个新的高值,再次关闭程序并重新运行 1000 次试验,我可能会从 10M 样本中得到新的高值,因为它恰好是 1000 样本的高值,这非常不可能,尤其是使用我的实际代码,结果差异更大。

我认为 rand() 函数或我不理解的 c++ 语言发生了一些问题,这是造成这种情况的原因吗?感谢您的任何启发。

【问题讨论】:

  • 这是一个奇怪的randomNumber 函数。你能解释一下它应该做什么,因为我不介意打赌问题出在那个函数上。
  • 说出您看到的数字可能会有所帮助。是不是每次运行程序都完全一样。
  • 警告:使用rand() can be highly problematic,我们强烈建议您使用合适的random number generator facility in the Standard Library,以产生高质量的随机值。您使用time(NULL) 作为随机数种子意味着如果在同一秒内运行,这将产生相同的结果,并且在许多平台上rand()barely random at all

标签: c++ loops random statistics srand


【解决方案1】:

我不是统计学家,所以我的计算可能是错误的,但总体思路应该是正确的。

首先,让我们看看你的randomNumber() 函数,暂时忽略rand() 如何生成数字。

第一个 while 循环,有 1/250000 的机会通过。这意味着,平均而言,您已致电 rand() 约 250000 次。 (再次注意,我的数学概率不是很好)。

使用相同的逻辑,在完成整个randomNumber() 之后,您将调用rand() 487000 次。如果你已经调用了randomNumber() 1000 次,你就会调用rand() 487,000,000 次。

现在让我们看看rand()。基于几个来源:Rand Implementation OEIS - A096558 std::rand - cppreference 连续调用 rand() 实际上会生成一个 2^32 或 RAND_MAX 长度的非重复列表。你拥有的种子或srand(time(NULL)) 无关紧要,它只是同一列表的旋转版本。

由于您拥有的主要功能基本上只是获得randomNumber() 的最大结果,使用 4*10^8 / 2^32,您基本上会得到相同的 10 次。使用更大的TRIALS,您基本上会花更多时间得到相同的答案。而且在某个时间,你的答案永远都是一样的。

我没有无限的力量来运行它,但这是我运行TRIAL = 10000 20 次得到的:

958495, 141042, 2497
958495, 141042, 2497
958495, 141042, 2497
958495, 140987, 2497
958495, 140924, 2497
958495, 140924, 2497
958495, 140924, 2497
958495, 140911, 2497
958495, 140911, 2497
958495, 140911, 2497
958495, 140906, 2497
958495, 140796, 2497
958495, 140650, 2497
958495, 140650, 2497
958495, 140621, 2497
958495, 140586, 2497
958495, 140586, 2497
958495, 140586, 2497
958495, 140375, 2497
958495, 140271, 2497

【讨论】:

  • 谢谢!我用 chrono::high_resolution_clock::now().time_since_epoch().count() 为 mt19937 切换了 srand(time(NULL)) 和 rand() ,这应该是一个更好的随机数生成器,但我仍然遇到同样的问题。您是否会推荐一个随机数生成器,它可以无限地不产生重复序列,或者至少不会产生这么长时间我不会遇到问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-25
  • 1970-01-01
  • 2014-05-18
相关资源
最近更新 更多