我正在寻找C / C ++中随机数生成器的内部实现。基本上我很想知道调用rand()时究竟发生了什么。在所有机器都遵循一定的指令后,它怎么能是随机的!
编辑:想知道如何在C / C ++中实现一个。
答案 0 :(得分:11)
它们是伪随机数字生成器,而不是真正随机的生成器。这通常是好的事情,因为它允许您更容易地在涉及“随机”数字的情况下重现错误。
您可以获取随机数生成器,例如在Linux下读取/dev/random
,但通常不包含C库的正常数据生成器。
最简单的是线性同余生成器,其中:
n(x+1) = n(x) * A + C modulo M
适当选择A
,C
和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;
}
,所以这很简单:
/dev/random
除此之外:glibc实现中仍然有这个生成器(称为Type 0生成器),但它也有一个更高级的三项式生成器,它(可能)更好。
还有更复杂的(如梅森捻线机)具有更长的周期时间(开始重复之前的时间)。
任何真正随机的生成器必须使用真正的随机输入源,这就是/dev/urandom
有时会阻塞(“等待熵”)的原因,而{{1}}则不会。
“真正”的随机来源可能会受到按键之间的时间间隔,数据输入的数据,网络数据包的内容,磁盘I / O模式,ICMP响应通过网络返回所花费的时间以及各种其他因素的影响。奇妙的,主要是非确定性的东西。
除非你非常重视加密,否则正常的随机数生成器就可以了。
答案 1 :(得分:1)
正如我在评论中所说,RAM机器的随机生成器并非真正随机,它们是pseudo-random。
您可以随时查看java.util.Random的java源代码。
具体来说 - 方法next(int bits)
就是你要找的。 p>
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
(*)这个答案适合该问题的先前版本,该版本被标记为java并且没有专门针对C ++。
答案 2 :(得分:1)
这是一个简单的伪随机算法:
//generates pseudo random series of numbers 0...RAND_MAX - 1 with uniform distribution, starting with 0
static const int A = 15342; // any number in (0, RAND_MAX)
static const int C = 45194; // any number in [0, RAND_MAX)
static const RAND_MAX = 100000;
int rand()
{
static int prev = 0; //seed. any number in [0, RAND_MAX)
prev = ( prev * A + C ) % RAND_MAX;
return prev;
}
您可以在此处阅读更多内容:http://en.wikipedia.org/wiki/Linear_congruential_generator
答案 3 :(得分:0)
我认为numerical recipies book将是一个很好的起点。