使用qsrand的随机方法不是真正的随机

18

我这里遇到了一个奇怪的问题,但我找不到好的解释,所以想向大家请教:

考虑以下方法:

int MathUtility::randomize(int Min, int Max)
{
    qsrand(QTime::currentTime().msec());

    if (Min > Max)
    {
        int Temp = Min;
        Min = Max;
        Max = Temp;
    }
    return ((rand()%(Max-Min+1))+Min);
}

我不会向专家解释这个方法实际上的作用,而是解释我的问题:

我意识到当我在循环中调用这个方法时,有时会一遍又一遍地得到相同的随机数...例如,下面的代码片段...

for(int i=0; i<10; ++i)
{
    int Index = MathUtility::randomize(0, 1000);
    qDebug() << Index;
}

这将产生类似以下的内容:

567 567 567 567...等等...

我也意识到,如果我不每次调用qsrand函数,而仅在应用程序的生命周期中调用一次,它就可以完美地工作...

我的问题是:为什么?

7个回答

36
因为在当前CPU时钟速度下,如果在1毫秒内调用randomize多次(这是很有可能的),则每次都将使用相同的值来初始化随机数生成器。这 保证 会产生相同的随机数输出。
随机数生成器只应该被初始化一次。多次初始化不会使输出更加随机,实际上(正如您发现的那样)可能会使输出变得更加 随机。

1
谢谢,伙计。为了语法的完整性,这里有两行示例代码:1:qsrand(QTime::currentTime().msec()); 2:int number = rand() % (100-0+1)+0; 只需将100替换为您的最大值,将0替换为您的最小值即可。 - kayleeFrye_onDeck

2
如果你调用得足够快,QTime::currentTime().msec() 的值不会改变,基本上是用相同的种子重新播种 qsrand,导致下一个随机数与前一个相同。

2
如果您调用qsrand Qt函数来初始化种子,您必须调用qrand Qt函数生成随机数,而不是标准库中的rand函数。对于rand函数的种子初始化,使用srand函数。抱歉打扰了。

1
你看到的是伪随机性的效果。你用时间种子一次,它就会生成一个数字序列。由于你在不断快速地提取一系列随机数,所以你正在使用相同的数字重新播种随机生成器,直到下一毫秒。虽然一毫秒似乎很短暂,但请考虑在此期间进行的计算量。

1

现代 Qt C++ 11

#include <random>
#include "QDateTime"

int getRand(int min, int max){
    unsigned int ms = static_cast<unsigned>(QDateTime::currentMSecsSinceEpoch());
    std::mt19937 gen(ms);
    std::uniform_int_distribution<> uid(min, max);    
    return uid(gen);
}

0

两个问题:

1.正如其他人指出的那样,生成器被多次种子化。

2.这不是在给定范围内生成随机数的很好的方法。(实际上对于大多数生成器来说非常非常糟糕)

您假设生成器的低位比特是均匀分布的。但是大多数生成器并非如此。在大多数生成器中,随机性发生在高位比特中。

通过使用除法后的余数,您实际上是在丢弃随机性。

您应该使用乘法和除法进行缩放。而不是使用模运算符。 例如:

my_number= start_required + ( generator_output * range_required)/generator_maximum;

如果generator_output在[0,generator_maximum]之间,则my_number将在[start_required,start_required+range_required]之间。


0

我发现了相同的问题,并通过使用rand()而不是srand()来解决它。

但我只是用它来检查我的应用程序。它只在循环中工作,所以我不需要寻找更新。

但如果你要做某种游戏,这不是一个好方法,因为你的随机化将是相同的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接