我对C中随机数生成器的实现感到有些困惑,这也明显不同于C ++中的随机数生成器
如果我理解正确,调用'srand(seed)'会以某种方式初始化一个隐藏变量(种子),该变量可以被'rand()'访问,而后者又将该函数指向预先生成的序列,如为example this one。每次连续调用'rand()'都会使序列前进(显然还有其他方法可以在C ++中前进),这也建议使用内部隐藏指针或计数器来跟踪进度。
我发现很多关于伪随机数生成算法如何工作以及函数rand()和srand()的文档的讨论,但是却无法找到有关这些隐藏参数及其行为的信息,除according to this source之外,它们不是线程安全的。
请问这里的任何人请详细说明这些参数是如何定义的,根据标准定义的行为应该是什么,或者他们的行为是否是实现定义的?
它们是否应该是调用rand()和srand()的函数/方法的本地?如果是这样,有没有办法将它们传达给另一个函数/方法?
如果您的答案特定于C或C ++,请非常友好地指出它。任何信息将不胜感激。请记住,这个问题不是关于predictability of data generated by rand() and srand(),而是关于内部变量的要求,状态和功能以及它们的可访问性和范围。
答案 0 :(得分:6)
rand
的要求是:
RAND_MAX
(最小值32767)。srand()
设置的种子确定返回的伪随机数序列。标准没有定义任何方法来恢复重播或其他任何内部状态。
对PRNG的实施没有要求,因此每个实现都有自己的实现,但Linear Congrueantial Generators是最受欢迎的。
这个dilbert条带中提供了一个符合(虽然可以说是无用的)实现:
http://dilbert.com/strips/comic/2001-10-25/
对于那些喜欢XKCD的人(它是任何C或C ++库的完美插件; - )):
为完整起见,标准引用:
7.22.2.1 rand 功能
rand 函数计算0到0范围内的伪随机整数序列 的 RAND_MAX 即可。
rand 函数不需要避免与其他伪随机调用的数据竞争 序列生成函数。实现应该表现得好像没有库函数 调用 rand 函数。
[...]
RAND_MAX 宏的值至少应为32767。7.22.2.2 srand 功能
srand 函数使用该参数作为新随机伪随机序列的种子 后续调用 rand 返回的数字。如果随后调用 srand 在相同的种子值下,应重复伪随机数的序列。如果 rand 是 在对 srand 进行任何调用之前调用,应生成相同的序列 当第一次调用 srand 时,种子值为1 不需要 srand 函数来避免与其他伪随机调用的数据竞争 序列生成函数。实现应该表现得好像没有库函数 调用 srand 函数。
C ++包含rand
,srand
和RAND_MAX
,不会因C标准的引用而改变。
有一些C ++库函数/类被明确记录,但使用C随机数生成器。
答案 1 :(得分:3)
以下答案适用于C;特别是1999年的标准。
C99标准对rand
&的实际实施细节非常清楚。 srand
。它只是声明srand
的参数“作为seed用于后续调用rand
返回的新的伪随机数序列。”
在实践中,它通常的工作方式是:
rand
和srand
用来跟踪PRNG状态的整数变量。srand
将状态变量设置为提供的值。rand
获取状态变量的值并对其执行一些数学魔术以产生两个新的整数:一个是它返回的伪随机数,另一个是状态变量的新值,从而影响对rand
的下一次调用(假设在此之前未调用srand
)。 C标准提供了展示此行为的rand
和srand
的可能实现示例:
static unsigned long int next = 1;
int rand(void) // RAND_MAX assumed to be 32767
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
void srand(unsigned int seed)
{
next = seed;
}