C:随机数生成 - 什么(如果有的话)错了

时间:2010-04-06 16:07:27

标签: c random

对于C中的简单模拟,我需要生成指数随机变量。我记得在某个地方读过(但我现在找不到,我不记得为什么)使用rand()函数在固定范围内生成随机整数会产生非均匀分布的整数。因此,我想知道这段代码是否有类似的问题:

//generate u ~ U[0,1]
u = (   (double)rand() / ((double)(RAND_MAX));
//inverse of exponential CDF to get exponential random variable
expon = -log(1-u) * mean;

谢谢!

5 个答案:

答案 0 :(得分:5)

固定范围内的随机数问题是很多人为100到200之间的数字执行此操作,例如:

100 + rand() % 100

这不统一。但通过这样做,它(至少足够接近均匀):

u = 100 + 100 * ((double)rand() / ((double)(RAND_MAX));

既然你正在做的事情,你应该是安全的。

答案 1 :(得分:2)

理论上,至少,rand()应该给你一个从0到RAND_MAX的离散均匀分布......在实践中,它有一些不合需要的属性,比如一个小周期,所以它是否有用取决于你的方式重新使用它。

答案 2 :(得分:2)

RAND_MAX通常为32k,而LCG rand()使用生成伪随机32位数。因此,缺乏一致性以及低周期性通常会被忽视。

如果您需要高质量的伪随机数,您可以尝试使用George Marsaglia的CMWC4096(带有Carry的互补乘法)。这可能是最好的伪随机数发生器,具有极端的周期性和均匀分布(你只需为它选择好的种子)。此外,它的速度非常快(不如LCG快,但速度大约是Mersenne Twister的两倍。

答案 3 :(得分:1)

是和否。当您将输出从rand()钳制到小于 <{1}}的范围时(即输出的输出可能少于输入),就会出现您正在考虑的问题。

在你的情况下,你(正常)反转:你占用了随机数发生器产生的相当少的比特,并将它们分散在尾数中通常是较大数量的比特之间。你的双倍。这意味着在double中通常会有一些位模式(因此,double的特定值)永远不会发生。对于大多数人来说,这不是一个问题。

就“正常”而言,总是有可能你有一个64位随机数发生器,其中一个双通常有一个53位的尾数。在这种情况下,您可能会遇到与使用整数限制范围相同的问题。

答案 4 :(得分:0)

不,你的算法会起作用;它使用模数函数来完成不完美的事情  一个问题是因为它是量化的,偶尔它会产生RAND_MAX,你会要求log(1-1)。我建议至少(rand() + 0.5)/(RAND_MAX+1),如果不是更好的来源,例如drand48()

有更快的方法来计算必要的数字,例如Ziggurat algorithm