c - C 中重复且可预测的 RNG 值

标签 c

<分区>

我试图在 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 的函数的开头,现在一切都很好!

最佳答案

不要每次要生成数字时都调用srandsrand 初始化伪随机数生成器,旨在仅在程序开始时调用一次,或者在您想要重置生成器时调用。通过每次重置它,您将强制 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 srandomrandom

关于c - C 中重复且可预测的 RNG 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50788970/

相关文章:

c - 全局范围和文件范围有什么区别?

c - 按位或和赋值

更改控制台窗口中的现有文本

通过/dev/mem 与 PCI 设备通信

objective-c - 从 .mm 文件中的函数内部调用 C 函数

python - 在 Windows (VC90) 中使用 C 绑定(bind)构建 Python 包导致 LNK1181 fatal error

c - 对 int 的输入验证

objective-c - 指向 struct C/ObjC 中指针的指针

c - Sem_open导致非法寻道错误

c - 将参数从 C 传递给汇编?