我试图在 C 中连续生成 10,000 个随机数,但在使用伪 RNG 获得随机或什至随机结果时遇到了问题。我以我认为应该创造均匀性的方式使用模数,它确实如此,但结果相当于 0,0,0,0,0,0,0,0,0,1,1,1,1,1 ,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3 等在另一个调用 RNG 的函数中循环运行时(4).
int RNG(int n) {
int range = RAND_MAX - (RAND_MAX % n);
srand(time(NULL));
int x = rand();
while (x > range) {
x = rand();
}
return x % n;
}
任何让它更接近 1,3,2,0,2,3,1,0,0,3,2,0,1 等的方法都将不胜感激!
谢谢!
编辑:感谢大家的回复!将播种移动到调用 RNG 的函数的开头,现在一切都很好!
不要每次要生成数字时都调用srand
。 srand
初始化伪随机数生成器,旨在仅在程序开始时调用一次,或者在您想要重置生成器时调用。通过每次重置它,您将强制 rand
在时钟的每一秒内每次调用它时生成相同的数字。
不要使用 x % n
将数字减少到所需范围。 rand
的旧实现是出了名的糟糕并且在低位有模式。相反,请使用 x/((RAND_MAX+1u)/n)
。
代码 int range = RAND_MAX - (RAND_MAX % n);
有缺陷。假设n
为4,RAND_MAX
为7,表示rand
返回0到7。这段代码设置range
为4 ,然后 while (x > range) x = rand();
丢弃 5、6 和 7,同时保留 4。这里有两个错误:代码保留了五个值 0、1 、2、3 和 4,它们与所需范围 4 不匹配(不是倍数),它会不必要地丢弃值。如果我们保留 4、5、6 和 7,我们就会有一场比赛。你可以使用:
unsigned range = (RAND_MAX + 1u) - ((RAND_MAX + 1u) % n);
和:
while (x >= range) x = rand();
如果您使用的是 C++,请切换到使用 std::uniform_int_distribution
.如果您使用的是 C,请检查您的实现中 rand
的质量或切换到另一个生成器,例如 POSIX srandom
和 random
。