首页 > 解决方案 > 为什么我从随机数中得到相同的答案?

问题描述

嗨,我编写了一个 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++ 语言发生了什么导致这种情况?感谢您的任何启发。

标签: c++loopsrandomstatisticssrand

解决方案


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

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

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

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

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

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

我没有无限的力量来运行它,但这是我运行TRIAL = 1000020 次的结果:

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

推荐阅读