您将如何测试随机数生成器是否正在生成实际的随机数?
我的方法:首先构建一个大小为 M 的哈希,其中 M 是质数。然后取随机数生成器生成的数字,并用 M. 取 mod,看看它填充了所有散列或只是部分。这就是我的方法。我们可以用可视化来证明吗?
因为我对测试知之甚少。你能建议我彻底解决这个问题吗?提前致谢
您将如何测试随机数生成器是否正在生成实际的随机数?
我的方法:首先构建一个大小为 M 的哈希,其中 M 是质数。然后取随机数生成器生成的数字,并用 M. 取 mod,看看它填充了所有散列或只是部分。这就是我的方法。我们可以用可视化来证明吗?
因为我对测试知之甚少。你能建议我彻底解决这个问题吗?提前致谢
您应该知道,您不能保证随机数生成器正常工作。请注意,即使是 [1,10] 范围内的完美均匀分布 - 在 10 个数字的随机抽样中,有 10 -10的机会获得 10 乘以 10。
有可能吗?当然不是。
那么——我们能做些什么呢?
我们可以统计证明,如果随机数生成器确实是均匀分布的,则组合 (10,10,....,10) 是不可能的。这个概念称为假设检验。使用这种方法,我们可以说“以 x% 的确定性水平 - 我们可以拒绝数据取自均匀分布的假设”。
一种常见的方法是使用Pearson's Chi-Squared test,这个想法与你的相似 - 你填写一个表格 - 检查每个单元格的观察(生成)数字是多少,以及预期的数字是多少零假设下每个单元格的数字(在您的情况下,预期为k/M
- 其中 M 是范围的大小,k 是所取数字的总数)。
然后,您对数据进行一些操作(有关此操作的详细信息,请参阅维基百科文章) - 并获得一个数字(测试统计数据)。然后检查这个数字是否可能来自卡方分布. 如果是——你不能拒绝原假设,如果不是——你可以用 x% 的把握确定数据不是从一个统一的随机生成器中获取的。
编辑:示例:
您有一个立方体,并且您想检查它是否“公平”(均匀分布在 中[1,6]
)。抛出 200 次(例如)并创建下表:
number: 1 2 3 4 5 6
empirical occurances: 37 41 30 27 32 33
expected occurances: 33.3 33.3 33.3 33.3 33.3 33.3
现在,根据 Pearson 的检验,统计数据为:
X = ((37-33.3)^2)/33.3 + ((41-33.3)^2)/33.3 + ... + ((33-33.3)^2)/33.3
X = (18.49 + 59.29 + 10.89 + 39.69 + 1.69 + 0.09) / 33.3
X = 3.9
对于 random C~ChiSquare(5)
,更高的概率3.9
是~0.45
(这不是不可能的)1。
所以我们不能拒绝原假设,我们可以得出结论,数据可能均匀分布在[1,6]
(1) 如果值小于 0.05,我们通常会拒绝原假设,但这取决于具体情况。
我天真
的想法:生成器遵循分布。(至少应该如此。)进行合理数量的运行,然后将值绘制在图表上。在这些点上拟合回归曲线。如果它与分布的形状相关,那么你很好。(这也可以在 1D 中使用投影和直方图。并且可以使用正确的工具完全自动化,例如 MatLab)
您还可以使用前面提到的顽固测试,这肯定更好,但涉及的直觉要少得多,至少在您的边。
假设您想在区间 [0, 1] 上生成均匀分布。
然后一种可能的测试是
for i from 1 to sample-size
when a < random-being-tested() < b
counter +1
return counter/sample-size
并查看结果是否接近于 ba(b 减去 a)。
当然,您应该定义一个函数,将 0 和 1 之间的 a、b 作为输入,并返回 counter/sample-size 和 ba 之间的差值。循环遍历可能的 a、b,例如 0.01 的倍数,a < b。当差值大于预设的 epsilon(例如 0.001)时,打印出 a、b。
那些是有太多异常值的a,b。
如果您让样本大小为 5000。您的随机测试总共将被调用约 5000 * 5050 次,希望不会太糟糕。
我有同样的问题。当我完成编写代码时(使用外部 RNG 引擎)
我查看了结果,发现每当我有很多结果时,它们都没有通过卡方检验。
我的代码生成一个随机数并保存每个结果范围的数量。当我有很多结果时,我不知道为什么卡方检验会失败。
在我的研究中,我看到 C# Random.next() 在任何随机范围内都失败了,并且其中一些数字比另一个数字具有更好的几率,而且我还看到 RNGCryptoServiceProvider 随机提供程序不支持大数字。
当尝试获取 0-1,000,000,000 范围内的数字时,0-300M 范围内的数字出现的几率更高......
因此,我使用的是 RNGCryptoServiceProvider,如果我的范围高于 100M,我将结合我自己的数字(RandomHigh*100M + RandomLow),并且两个随机数的范围都小于 100M,所以很好。
祝你好运!