如何测试随机发生器

时间:2010-01-25 06:32:21

标签: testing random

我需要测试一个随机生成数字的随机数生成器。如何确保生成的数字是随机的。

13 个答案:

答案 0 :(得分:11)

使用卡方检验。你用的是什么语言?我可以提供一个C ++示例。基本上

  • 将随机数放入桶中(多次)。
  • 水桶数量减一,即degrees of freedom
  • 将桶标记与“预期”标记进行比较,得出卡方结果。
  • 使用chi-square calculator查看获得这些结果的可能性。

答案 1 :(得分:9)

无论如何,您只能测试统计随机性,但这并不能证明数字序列是否具有加密强度。统计测试PRNG需要相当多(10甚至100G字节)的生成位。

Dieharder是一个非常好的测试套件。

http://www.phy.duke.edu/~rgb/General/dieharder.php

TestU01也是众所周知的。

http://www.iro.umontreal.ca/~simardr/testu01/tu01.html

答案 2 :(得分:6)

以下是如何开始的详细说明。任何RNG的初步测试是NIST使用的Monobit测试,它只计算1和0的数量。 http://csrc.nist.gov/groups/ST/toolkit/rng/stats_tests.html

关于测试随机数生成器的注意事项: 我们实际上并不需要太多的RNG测试,因为许多"包含"彼此。

那就是说,这里描述的是一个简单有效的新的有序频率测试用于比特。该测试包含任何预期50-50的频率测试,因为它更严格。

定义:t = tosses / trials b = bins / urns s =投掷会话n =会话集

因为掷硬币通常不是50-50,所以使用40,000,000位的资源可以非常有效地利用这项新测试。

当硬币翻转100次时,预期值为53.9795的一个和46.0205的另一个,有时更多的头,有时更多的尾巴。 50-50不是有序箱的预期值,因此该测试优于任何频率测试,而不是预期50-50。

步骤1:样本大小的选择:100次/位。

第2步:选择会话数量:50个会话永远不够,即使数百万的样本量很大。 400通常就足够了。 2000收敛良好,因此使用了2000个不同的100个样本的样本。最低增益发生在2000以上。

2000次100次投掷的预期值:   50-50 159.1784748(请注意,50-50只发生在7.96%的时间。)   51-49 312.1146564   52-48 294.1080416   53-47 266.362   54-46 231.8335926   55-45 193.8971865   56-44 155.8102392   57-43 120.2745706   58-42 89.16907819   59-41 63.47629295   60-40 43.37546685   61-39 28.4429291   62-38 17.89152   63-37 10.79171042   64-36 6.238957586   65-35 3.455422663
  66-34 1.832421109   67或以上1.747439674

获得b = 2和t = 100的精确百分比的公式为: 对于100-0,赔率为1 /(2 ^ 99)= 1 /(2 ^(t-1)) 然后,从那里建立, 对于99-1之前的乘以100(t)除以1 对于98-2之前的乘以99(t-1)除以2 对于97-3之前的乘以98(t-2)除以3 ......跳过...... 51-49之前乘以52(t-48)除以49 50-50先前乘以51(t-49)除以50,然后再除以2.

此等式适用于任意数量的投掷。

步骤3:对这18个值进行卡方检验,得到17个自由度,得到p值。

p值高于0.999接近完美。 RNG太过接近完美吗?是的,太可预测了。 0.001以下是通常会出现明确问题的地方。一个测试套件将小数点右边的300个零视为无穷小,连续10-14个非常糟糕。有些人认为6个零已足够严重,无法成为明确的明确失败。为安全起见,有些人会考虑1或2个零而且它们是错误的。因此,对于单个集合而言,有时为优秀的RNG提供低于0.01的p值,而不是单个p值,而是采用了多组会话。

步骤4:将p值送入0-1.0直线Kolmogorov-Smirnov检验。不同的专家建议K-S测试的输入数量从10到1000. 100还不够。 200很好。 500略有攻击性。

这是获得K-S最大差异的伪代码:

Set low := 0;  Set n := 200;  
Set ansForward := 0; Set ansBack := 0;

sort( pval [n] );
for (j := 0; j < n; j := j+1)   
 {  Set Kback := pval [ j ] - low;
    Set low := low +1 / n;    { Ranges from 0 to 1 }
    Set Kforward := low - pval [ j ];  
    if (Kforward > ansForward) Set ansForward := Kforward;
    if (Kback > ansBack) Set ansBack := Kback;
   }
{ Separate analysis can perhaps be made here on ansForward and ansBack.  Someone like Peter Brand might also examine and magnify the bottom 5% and the top 5%. }
if (ansForward > ansBack)
      return ansForward;
else
      return ansBack;   ∎

K-S答案不是p值,200 p值不应超过0.115。对于良好的RNG,0.03至0.08是正常的。 0.115至0.13是可疑的。

K-S测试非常简单它也很有效。

上面显示的是一种优质的新有序频率测试。任何未通过此测试的RNG都不应进一步测试并立即更换。但是,接下来呢?

OFTest不包含LOR测试。建议使用长度测试,样本大小为200,000,其中15个自由度进入K-S测试200次。 (注意,&#34;大于j&#34;的最小LOR bin的预期总数等于第j个bin。)

然后是什么?对于许多游戏,这两个测试都是您需要的。 NIST,Diehard,Dieharder,Crusher倾向于选择。 (注意:Diehard Overlapping Sums测试既低劣又有缺陷,不是对Marsaglia原始Fortran代码的忠实解释。)

一些n = 200的RNG的结果。

  1. LCG 134775813x + 1 mod 2 ^ 31 seed = 11111: 高位:OFT KS:0.0841通过。 LOR KS:0.04786通过。第一个200,000的单比特:-189通行证。 位16:OFT KS:0.5477失败。第一个200,000:114通行证的单比特。 从0到15的所有位都不通过OFT,但通过了Monobit测试。

  2. 经常被诽谤的LCG Randu:65539x + 0 mod 2 ^ 31 seed = 11111:
    高位:OFT KS:0.03567 LOR KS:0.07709。第一个200,000的单比特:-165 位18:OFT KS:0.15143第一个200,000的单比特:+204 从0到17的所有位都无法通过OFT。

  3. LCG 69069x + 1 mod 2 ^ 32 seed = 11111: 高位:OFT KS:0.05547 LOR KS:0.0456单位数200,000:-290 第17位:OFT KS:0.1467单比特200,000:-193 从0到13的所有位都不能通过OFT。

  4. LCG 3141592653x + 2718281829 mod 2 ^ 35 seed = 11111: 高位:OFT KS:0.02868 LOR KS:0.06117单位数200,000:-69 位16:OFT KS:0.240单比特200,000:-13 从0到15的所有位都不能通过OFT。

  5. LCG 23x + 0 mod 2 ^ 27 seed = 11111: 高位:OFT KS:0.5368单位数200,000:-235 所有位都未通过OFT。

  6. 请注意,应该从返回的结果中丢弃任何LCG的低位。

    关于2 ^ 35的注释:这是任何RNG的最小周期和重要性,因为硬币翻转和掷骰子运行,这样的事情可能连续发生30次,但预计不会发生35次。 2 ^ 32的时期是不够的,对于现实生活情况来说太小了。

    LWAP

答案 3 :(得分:4)

  

如何确保生成的数字是随机的。

你不能确保,没有办法使用有限数量的测试来确定随机数生成器中的任何函数。但你可以做Statistical Analysis

  

因此,如果无法明确证明随机性,我们可以做些什么呢?实用的方法是从给定的发电机中获取许多随机数序列,并对它们进行一系列统计测试。当序列通过更多测试时,对数字随机性的信心增加,对发生器的置信度也增加。然而,因为我们期望一些序列看起来是非随机的(比如我们的死亡中的十个六卷),我们应该期望一些序列至少在一些测试中失败。但是,如果许多序列未通过测试,我们应该怀疑。这也是你直观地测试骰子是否被加载的方式:滚动它多次,如果你看到太多相同值的序列出现,你应该怀疑。

有关您可以运行的测试的详细信息,请参阅Charmaine Kenny的研究部分。

答案 4 :(得分:3)

这是一件非常困难的事情。

您可以尝试ENT中的Fourmilab,并将其与针对其RNG HotBits的结果进行比较。您可能还想查看Random.org

这看起来也很有趣:Diehard tests(我虽然没有使用它)。

答案 5 :(得分:2)

您无法确保数字是随机的,因为随机数是随机

获得一百万个连续9的字符串的机会与获得任何其他特定的一百万个序列相同。您可以检查的一件事是在大样本集上正确分发。运行一个相当大的测试,并计算每个可能结果的相对出现次数。

在足够大的样本上,它们应该大致相同。

另一种可能性是测试不可重复性。理想情况下,随机数不应取决于之前的数字。非常简单(线性同余)PRNG很可能最终会给你相同的数字序列,但是你可能不会关心一个足够大的数组(除非你严重关于随机性)。

答案 6 :(得分:2)

将它展示给一个满是开发人员的房间。

答案 7 :(得分:1)

通常,如果你在位图中的随机位置有你的生成器绘制点,那么任何非随机性都很容易被眼睛看成丛生,条带或线条。

答案 8 :(得分:1)

创建一个日志文件,其中包含至少500个实例的随机数,并审核其随机性。另请看下面的链接,

http://burtleburtle.net/bob/rand/testsfor.html

答案 9 :(得分:1)

这取决于您对随机性的要求有多严重。如果它不是太严重,我所做的是生成大量随机数,找到它们的频率,然后使用频率使用像Open Office中那样的spreadshhet绘制图形。如果分布看起来不错,那么我很高兴。

答案 10 :(得分:1)

这个puprose有一个很好的工具:http://www.phy.duke.edu/~rgb/General/dieharder.php

例如,您可以测试内置urandom

cat /dev/random | dieharder -a -g 200

或者编写自己的脚本,创建一个随机数的文件

dieharder -a -g 202 -f random.txt

答案 11 :(得分:0)

除非您可以访问随机数生成器并且可以使用它随意生成数字,否则无法测试数字序列是否随机。想一想:你有一个随机数发生器。假设它是一个统一的随机数生成器,生成[0,9]范围内的随机整数。给定一个序列:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9

你能告诉它是否是随机的吗?存在有限概率10 -10 ,我们的均匀随机数发生器将生成这个精确序列。实际上,给定任何长度为10的序列,我们具有生成该序列的均匀随机数生成器的相同概率。因此,根据定义,您无法确定给定序列是否是随机的。

如果您确实可以访问生成器本身,并且可以使用它来生成多个序列,那么“检查随机性”是有意义的。为此,我会看Diehard tests。有各种各样的实现。

答案 12 :(得分:-1)

您无法通过任何算法生成真正的随机性,因此尝试可视化您的输出并用自己的眼睛检查模式。没有随机生成器(通过算法)会创建一些模式,您可以自己判断它们。以下是该想法的演示之一:http://www.alife.co.uk/nonrandom/