4. 随机性测试的统计语言
随机数发生器输出的比特流看起来“像不像随机”,不能靠肉眼判断,也不能靠“感觉均匀”下结论。NIST STS、Dieharder、TestU01 这些测试套件,本质上都在做同一件事:把一段比特流交给某个统计量,算出它在“理想随机”假设下出现的概率,再据此判断这段序列是否可疑。要读懂它们的输出,必须先掌握一套统计语言:假设检验、显著性水平、p 值、两类错误,以及多重比较问题。
一、假设检验:把“随机”变成一个可检验的命题
假设检验的核心思路是“反证”。我们先把待检验的命题设为原假设 H₀,在本课程中通常就是“该比特流来自理想随机源,比特独立且 0/1 等概率”。与之对立的备择假设 H₁ 是“该比特流不满足理想随机性”。
但“随机”本身无法被直接证明,只能通过某个统计量间接观察。于是我们构造一个检验统计量,例如频数检验中的 0/1 计数偏差、游程检验中的游程长度分布、块内频数检验中的块内 1 的比例。在 H₀ 成立时,这个统计量的分布是已知的——通常近似服从正态分布、χ² 分布或其它标准分布。把实际观测值代入,就能算出“在 H₀ 为真时,出现当前或更极端结果的概率”,这就是 p 值。
因此,一次随机性测试的完整逻辑链是:设定 H₀ → 选择统计量 → 推导 H₀ 下的分布 → 计算观测值 → 得到 p 值 → 与显著性水平比较 → 做出判断。NIST STS 的每一项测试,都是这条链的一个具体实例。
二、显著性水平 α 与 p 值:判断的标尺
显著性水平 α 是我们事先设定的“容忍犯错的阈值”,表示在 H₀ 为真时,我们愿意以多大概率错误地拒绝它。工程中常用 α = 0.01,NIST STS 默认也采用 0.01。α 越小,判断越保守,越不容易把合格序列误判为不合格,但也越容易漏掉真正有问题的序列。
p 值 是数据给出的证据强度。判断规则非常直接:
- 若 p ≥ α,不拒绝 H₀,认为该测试未发现异常;
- 若 p < α,拒绝 H₀,认为该测试发现异常,序列在该项上不合格。
需要特别强调:p 值不是“序列是随机的概率”,也不是“H₀ 为真的概率”。它只是“在 H₀ 为真时,观测到当前或更极端结果的概率”。p = 0.03 并不意味着“有 3% 的概率是随机的”,而是“如果序列真的随机,出现这种偏差的概率约为 3%”。这是初学者最容易误解的地方。
三、第一类错误与第二类错误
任何基于阈值的判断都会犯错,错误分两类:
| 错误类型 | 含义 | 概率 | 后果 |
|---|---|---|---|
| 第一类错误(弃真) | H₀ 为真却拒绝它 | α | 把合格随机源误判为不合格 |
| 第二类错误(取伪) | H₀ 为假却不拒绝它 | β | 把有缺陷的随机源误判为合格 |
α 由我们事先设定,β 则取决于真实偏差大小、样本长度和检验方法,通常难以精确控制。二者存在权衡:降低 α 会减少误杀,但会增大 β,使弱偏差更难被发现。在随机数检测中,增大样本长度、增加测试项、使用更敏感的统计量,都可以在保持 α 不变的前提下降低 β。
这里有一个工程上的关键认识:“通过测试”不等于“证明随机”。它只意味着“在给定样本长度和显著性水平下,没有发现足以拒绝 H₀ 的证据”。一个设计糟糕的伪随机发生器,完全可能通过某一项测试,却通不过另一项。
四、多重比较问题:为什么不能只看单项结果
NIST STS 包含 15 项测试,每项又可能产生多个 p 值;Dieharder 的测试项更多。如果对每个 p 值都独立地用 α = 0.01 判断,那么即使输入是完全理想的随机序列,也会有一定比例的测试“偶然失败”。
假设有 m 个相互独立的检验,每个检验在 H₀ 为真时误拒概率为 α,则至少出现一次误拒的概率约为 1 − (1 − α)m。当 m = 100、α = 0.01 时,这个概率约为 63%。也就是说,即使序列完全合格,也大概率会看到若干项 p < 0.01。这就是多重比较问题。
处理多重比较的常见方法有三类:
- Bonferroni 校正:把单项阈值改为 α/m。简单保守,但 m 很大时过于严格,容易漏检。
- 比例判据:NIST STS 采用的方式。它不要求所有 p 值都 ≥ α,而是统计 p < α 的比例,并检查该比例是否落在置信区间内。例如 1000 个 p 值中,允许约 1% 落在 [0, 0.01) 区间,但若显著超过这个比例,则判定异常。
- p 值均匀性检验:把所有 p 值收集起来,用 χ² 或 KS 检验判断它们是否服从均匀分布。若 p 值整体偏小或分布畸形,说明发生器存在系统性问题。
因此,实际使用 NIST STS 时,正确做法不是“逐项看有没有 p < 0.01”,而是:先看各测试项的 p 值通过比例,再看 p 值整体分布是否均匀,最后结合具体失败项定位问题。单点失败可能是偶然,系统性失败才指向真正的缺陷。
五、把统计语言落到测试套件上
理解了上述概念,再看 NIST STS 的输出就不会迷惑。它给出的每一项 p 值,都是在 H₀ 下计算出的证据强度;它给出的“通过比例”,是在处理多重比较;它给出的“p 值均匀性检验结果”,是在检查整体分布是否正常。Dieharder 的 -a 全量测试、TestU01 的 BigCrush 套件,同样遵循这套逻辑,只是测试项更多、统计量更复杂。
实际判断时,建议按以下顺序阅读结果:
- 先看总体通过比例是否接近 1 − α,而不是逐项盯 p 值;
- 再看 p 值是否整体服从均匀分布,若大量 p 值偏小,说明存在系统性偏差;
- 最后定位具体失败项,结合该测试的统计含义分析原因,例如频数检验失败指向 0/1 比例失衡,游程检验失败指向局部相关性;
- 若只有个别项偶然失败,可增大样本长度复测,观察失败是否稳定复现。
这套统计语言是后续所有随机性测试工具的共同基础。掌握了 H₀、α、p 值、两类错误和多重比较,就能把测试套件输出的数字翻译成对随机源质量的可靠判断,而不是被单个 p 值牵着走。