我只是好奇,单线程程序可以连续两次调用rand()
获得相同的返回值吗?
那么,这个断言会不会发生?
assert(rand() != rand());
答案 0 :(得分:46)
如果我们能找到一个例子,你问题的答案是"是"。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
unsigned int i;
for(i = 0; ; i++) {
int r = rand();
if (r == rand()) {
printf("Oops. rand() = %d; i = %d\n", r, i);
break;
}
}
return 0;
}
使用Visual Studio 2010在Windows上打印Oops. rand() = 3482; i = 32187
。
编辑: 使用下面的版本检测2个连续rand()调用返回相同值的所有序列。 C仅指定rand()应返回0到0范围内的&#34;伪随机整数 RAND_MAX&#34;和RAND_MAX应至少为32767。 对PRNG的质量或其实现没有限制,或者其他细节,例如2个连续的rand()调用是否可以返回相同的值。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
unsigned int i;
int r1 = rand();
int r2 = rand();
for(i = 0; ; i++) {
if (r1 == r2) {
printf("Oops. rand() = %d; i = %d\n", r1, i);
}
r1 = r2;
r2 = rand();
}
return 0;
}
答案 1 :(得分:30)
发现我的编译器(msvc10
)的rand实现确实使用了线性同余生成器,就像其他c / c ++编译器一样
线性同余生成器使用递归方法。
ptd-&gt; _holdrand(n)永远不会等于ptd-&gt; _holdrand(n + 1),但mod结果将相等。
@nos显示结果
return( ((ptd->_holdrand = ptd->_holdrand * 214013L + 2531011L) >> 16) & 0x7fff );
ptd->_holdrand = 2375716238;
return 3482; (2375716238 >> 16) % 32768
ptd->_holdrand = 228240921;
return 3482; (228240921 >> 16) % 32768
最终答案是rand()将作为我的直觉两次返回相同的值。
答案 2 :(得分:8)
理想的随机rand()
函数,如果调用两次,每次都会返回相同的结果,概率为1.0 / RAND_MAX
。
但rand()
不是真正的随机数生成器。它是pseudorandom number generator(PRNG),通常为linear congruential类型。
PRNG的内部状态不得在连续呼叫时重复;如果确实如此,rand()
会永远陷入同一个数字。对于像middle square method这样设计不佳的算法,可能会发生这种情况。
然而,一些(但不是全部)PRNG实现在其内部状态中具有比在其输出中更多的位。例如,java.util.Random
使用48位内部状态,但仅包含其输出中最重要的32位。在这种情况下,(至少在理论上)可以在没有相同内部状态的情况下连续两次获得相同的输出。
答案 3 :(得分:6)
一个好的随机数生成器应该有时连续两次返回相同的值。让我们说它返回正整数0&lt; = r&lt; 2 ^ 31。对于完美的随机数发生器,两个连续数字相同的可能性大约为20亿。 不在1000亿次通话中获得两个相同数字的机会大约是10 ^ 15中的一个。