C ++随机数发生器-第一个随机数始终是7的因子

时间:2018-11-12 17:17:31

标签: c++ random

我有一个简单的C ++程序,用来与学生一起演示对数组元素的随机选择。

和往常一样,在使用srand (time (0));生成数字之前,我先使用rand()作为种子。

该数组有七个条目,所选的条目是第一个-下标0。

我现在已经在40分钟内运行了15次该程序的版本,并且第一个随机生成的数字已经是7的倍数,例如:

1258771276 1258586399 1229409447 1257140997 1256216612 1260855344 1262973026 1266351233

我将程序更改为在播种后选择五个随机数,并且(在生成7的初始倍数之后),后续数字的表现更好。

我了解“随机”意味着我无法再预测数字相同,而无法预测它们相同。

我也理解这些是伪随机数。

我也了解rand()不应是顶级密码随机化。

仍然,这种行为太奇怪了,我完全感到惊讶。我是否陷入了C ++运行时的怪异裂缝?这是在完全修补到Mojave 10.14.1的MacOS上使用Xcode。

1 个答案:

答案 0 :(得分:1)

这是相关随机生成器的源代码:

static int
do_rand(unsigned long *ctx)
{
/*
 * Compute x = (7^5 * x) mod (2^31 - 1)
 * without overflowing 31 bits:
 *      (2^31 - 1) = 127773 * (7^5) + 2836
 * From "Random number generators: good ones are hard to find",
 * Park and Miller, Communications of the ACM, vol. 31, no. 10,
 * October 1988, p. 1195.
 */
    long hi, lo, x;

    /* Can't be initialized with 0, so use another value. */
    if (*ctx == 0)
        *ctx = 123459876;
    hi = *ctx / 127773;
    lo = *ctx % 127773;
    x = 16807 * lo - 2836 * hi;
    if (x < 0)
        x += 0x7fffffff;
    return ((*ctx = x) % ((unsigned long)0x7fffffff + 1));
}

考虑到当前最先进的发电机,这不是一个高质量的发电机。但是,它也不错。

但是,其播种机制可能是最糟糕的:它只是将ctx设置为种子。因此,如果您将种子设置为相似的值(就像您的示例一样,将其随时间播种,这意味着它将具有相似的值),则它生成的下一个数字将与种子具有非常强的相关性。

该问题的一种解决方案是在播种后生成“一些”数字。但是,它不能完美地解决问题(通常,即使非常很远的距离,种子与生成的数量也具有很强的相关性)。

或者,更好的解决方案是忘掉rand(),而使用更现代的(并且更难使用)随机变量,  在#include <random>中。  查看有关cppreference的documentation