我有一个简单的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。
答案 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。