如何在C中得到伪随机均匀分布的整数足以进行统计模拟?

我正在编写蒙特卡罗模拟,并且需要大量随机位来生成均匀分布在{1,2,…,N}上的整数,其中N <40。 使用C rand函数的问题是我使用标准rand % N技术浪费了很多非常好的位。 生成整数的更好方法是什么?

我不需要加密安全随机数,但我不希望它们扭曲我的结果。 另外,我不考虑从random.org下载一批比特解决方案。

rand % N不起作用; 它会扭曲你的结果,除非RAND_MAX + 1N的倍数。

一种正确的方法是找出小于RAND_MAXN的最大倍数,然后生成随机数,直到它小于该值。 只有这样才能进行模运算。 这使您的最差情况下的拒绝率为50%。

除了oli的答案:

如果你非常关心比特,那么你可以手工管理一个比特队列,只检索下一个数字所需的数量(即上限(log2(n)))。

但你应该确保你的发电机足够好。 简单的线性同余(sp?)发生器在较高位中比较低位(见注释)更好,因此您当前的模块化划分方法在那里更有意义。

数字食谱在所有这些方面有一个非常好的部分,并且非常容易阅读(不确定它提到保存位,但作为一般参考)。

更新如果您不确定是否需要,我现在不会担心这个问题(除非您从了解您特定背景的人那里得到更好的建议)。

在base40中表示rand并将数字作为数字。 丢弃任何不完整的数字,即如果没有全范围[0..39]则丢弃第一个数字,如果第一个数字取其最高可能值,则丢弃整个随机数(例如,如果RAND_MAX为base40,则21 23 05 06,丢弃所有具有最高基数-40位数的数字21)。