为什么使用 rand() 会有更高数字的概率

Why is there a probability of higher numbers using rand()

本文关键字:高数字 数字 概率 rand 为什么      更新时间:2023-10-16

我猜很奇怪的问题。这是出于好奇。

使用 rand() 函数,如果我们在 1-10 之间设置参数,然后我在我的机器 UNIX 操作系统上运行了几次测试,更具体地说是 Ubuntu。我的结果总是显示更高的数字(大于 5)更有可能返回。这似乎一点都不像是随机的。

我还阅读了模数,它指出使用模数运算,我们形成了某种偏差。

请注意,此模运算不会在跨度中生成均匀分布的随机数(因为在大多数情况下,此操作会使较小的数字更有可能)。

为什么?它还说较低的数字变得更有可能,但是我得到更多的数字

如何测试偏差

系统上的rand()生成器(glibc 中的生成器)有问题,但过度偏差不在其中。 假设您使用以下代码在给定范围内生成随机数。

int random_int(int min, int max)
{
    return min + rand() % (max - min + 1);
}

我们不要假设你播种数字。

int main(int argc, char **argv)
{   
    int histo[10];
    for (int i = 0; i < 10; i++) 
        histo[i] = 0;
    for (int i = 0; i < 10000; i++) 
        histo[random_int(1, 10) - 1]++;
    for (int i = 0; i < 10; i++)
        printf("%dn", histo[i]);
}

这将为我们提供 10,000 个样本,这很小但可行。 我得到以下结果。 如果您使用的是相同版本的 glibc,您将获得完全相同的版本。

10539801002959100994810361041987985

我们期望箱服从二项分布,给定一个无偏生成器。 对于 10,000 个样本,我们预计每个箱的方差为 Np(1-p) 或 900,这给出的标准差正好为 30。 我们的样本方差为 1105。 现在,我不会在这里做任何严格的事情......我要假装二项分布是正态的...我只是要做一个简单的卡方检验。 结果为 p=0.2。 不完全是诅咒。

因此,如果您想测试随机数生成器,请记住事后进行数学运算以解释测试结果。

模偏置

模偏差实际上增加了较低数字的概率,而不是较高数字的概率。 对于这样的范围(1..10),偏差非常小,因为对于glibc RAND_MAX是231-1,这使得小数字的概率增加了大约1/2亿。 您需要执行大量测试才能暴露模偏差。

不鼓励模的主要原因是因为常见rand()实现的低位显示出较差的独立性。 当然,您也不应该使用此技术来生成大范围。

建议

如果你真的想测试你的随机数生成器,我建议看看Marsaglia后期的"顽固"测试。 如果你只想要一个好的随机数生成器,你可以使用 arc4random, Mersenne Twister, or /dev/urandom . 根据您是开发加密应用程序还是使用蒙特卡罗模拟结果,您的选择会有所不同。