对于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;
谢谢!
答案 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。