为什么C ++ std :: rand()有模式?

时间:2013-08-08 10:14:48

标签: c++ random

所有

我带着一个简单的问题。请先阅读以下代码

int main()
{
    vector<double> arr1, arrr2;
    arr1.resize(120);
    arr2.resize(120);
    for(int i = 0; i < 120; i++)
    {
        double d1 = rand() % 100;
        d1 = d1/double(100);
        arr1[i] =d1;

        double d2 = rand() % 100;
        d2 = d2/double(100);
        arr2[i] =d2;

    }
    return 0;
}

在上面的代码中,我生成了两个随机数组(没有任何种子)。我将这些数组保存在文件中,并将其绘制如下:

enter image description here 从这张图片中,我发现这两个随机序列在改变数量方面有类似的趋势。例如这两个系列从(x = 57)到(x = 60),从(x = 82)到(x = 86)等一起上下移动。

我是否可以通过可视化误导我,或者确实存在某种相关性?

非常感谢提前。

祝福

3 个答案:

答案 0 :(得分:5)

你做了很多错事。

你做错的第一件事是使用rand()。那里有很多优秀的优秀随机数发生器。 rand()通常甚至不属于“好”类别。

您接下来要做的就是将整数结果从rand()转换为双精度

double d1 = rand() % 100;
d1 = d1/double(100);

这会丢弃rand()结果中的高电平位。即使是好的随机数发生器也可能存在低位的问题。诸如rand()的典型实现之类的不良随机数生成器几乎可以保证这种情况。相反,除以rand()RAND_MAX的最大可能结果(强制转换为双精度)。

接下来你做错了就是使用相同的伪随机序列来生成两个假设不相关的随机数序列。使用两个不同的生成器来做这件事要好得多。您无法使用rand()执行此操作。使用更好的PRNG。

你做错的最后一件事是看到一个可能不存在的模式。你需要使用比你的眼睛更强大的技术,如统计相关性。或者只使用更好的PRNG,经过多种方式测试,确保结果满足各种“随机性”测试。

答案 1 :(得分:2)

你的代码会有一个很小的偏差,因为RAND_MAX不能完全被100整除,并且你会丢掉除log2(100)位之外的所有精度,但你看到的相关性可能非常高 真实。标准C rand()是众所周知的低质量,因为它通常只是一个简单的线性同余发生器,并且已知几十年来任何严重使用都是不可接受的,但是图书馆作者是懒惰的。

查找具有更好PRNG算法的库。很多人可能会推荐像Mersenne Twister这样的东西,它很受欢迎,但不是最好的。现代生成器使用生成器函数的仔细组合,包括乘法,乘法,xor移位,滞后的fibbonacci(甚至LCG)之类的东西,并且无关算法的组合有助于消除相关性。

另请参阅Numerical Recipes的第7章。

答案 2 :(得分:1)

我没有看到模式的证据。人类思维是一种模式匹配机器,我们在任何地方都看到它们,并且随机性在我们看来是一种聚类倾向,所以在两个随机流中你可以期望找到具有看似匹配趋势的部分。