【发布时间】:2011-06-13 16:22:06
【问题描述】:
我想了解如何实现 rand() 和 srand() 函数,并想调整代码以根据我的要求进行修改。我在哪里可以找到 rand() 和 srand() 的源代码。
【问题讨论】:
我想了解如何实现 rand() 和 srand() 函数,并想调整代码以根据我的要求进行修改。我在哪里可以找到 rand() 和 srand() 的源代码。
【问题讨论】:
rand 和srand 通常实现为一个简单的LCG,您可以轻松编写自己的代码(几行代码),而无需查找rand 和srand 的来源。请注意,如果您出于“严肃”目的(例如密码学)需要随机数,则 RNG 比 LCG 好得多。
顺便说一句,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;
}
【讨论】:
它需要一个种子作为输入参数,通常如下:-
double result = srand(time(NULL));
并返回一个随机数,该随机数符合概率和预期的出现次数。
来自CodeGuru forums:-
void __cdecl srand (unsigned int seed)
{
#ifdef _MT
_getptd()->_holdrand = (unsigned long)seed;
#else /* _MT */
holdrand = (long)seed;
#endif /* _MT */
}
int __cdecl rand (void)
{
#ifdef _MT
_ptiddata ptd = _getptd();
return( ((ptd->_holdrand = ptd->_holdrand * 214013L + 2531011L) >> 16) &
0x7fff );
#else /* _MT */
return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
#endif /* _MT */
}
希望这会有所帮助。
【讨论】:
holdrand 会快速增长并很快导致溢出。 holdrand = holdrand * 214013L + 2531011L
double result = srand(time(NULL));:你到底为什么有那个double result? srand 没有返回值...
_MT 是处理多线程的代码(多线程运行时库为每个线程保留单独的 RNG 状态);请注意,这就是我避免发布实际库代码的原因:它通常包含与实际问题无关的“干扰元素”。
glibc (由 gcc 使用)是一个简单的公式:
x = 1103515245 * x + 12345
在 232 处环绕,如 here 所示。您可以将 x 设置为种子,然后继续调用函数来评估该表达式(并更新种子)。
但您应该知道,像这样的线性同余生成器被认为是足够的,但并不理想。
虽然唯一理想的随机数生成器是完全随机的,但Mersenne Twister 可能更接近。
【讨论】: