它们是 伪随机 数字生成器,而不是真正的随机数字生成器。这通常是一件好的事情,因为它可以让您更轻松地重现涉及“随机”数字的错误。
您可以获取随机数生成器,例如在 Linux 下读取 /dev/random,但 C 库附带的普通生成器通常没有。
最简单的是线性同余生成器,其中:
n(x+1) = n(x) * A + C modulo M
with suitably chosen values of A, C and M.
Wikipedia's page on LCGs 给出了各种实现使用的一些示例值。例如,那里列出的glibc 有a = 1103515245, c = 12345, m = 2^31,所以很简单:
static unsigned int seed = 1;
void srand (int newseed) {
seed = (unsigned)newseed & 0x7fffffffU;
}
int rand (void) {
seed = (seed * 1103515245U + 12345U) & 0x7fffffffU;
return (int)seed;
}
除此之外:glibc 实现中仍然有这个生成器(称为 0 型生成器),但它也有一个更高级的三项式生成器,它(可能)更好。
还有更复杂的(例如梅森捻线机),它们的循环时间(开始重复之前的时间)要长得多。
任何真正的随机生成器都必须使用真正随机的输入源,这就是为什么/dev/random 有时会阻塞(“等待熵”)而/dev/urandom 不会。
“真正的”随机源可能会受到击键之间的时间、用户输入的数据、网络数据包的内容、磁盘 I/O 模式、ICMP 响应通过网络返回所需的时间以及各种其他因素的影响奇妙的,大多是非确定性的东西。
除非你对加密非常感兴趣,否则普通的随机数生成器就可以了。