我正在尝试实现NIST Spectral Test(第 2.6 节)来测试 Python 中随机数生成器的随机性。该测试利用离散傅立叶变换来查找生成的比特流中的周期性趋势。我的代码如下所示:
from numpy import abs
from math import sqrt, log, erfc
from scipy.fft import fft
# ...
def nist_spectral_test(self):
binary_data = [1,1,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,1,1,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0,1,0,1,0,0,0,1,0,1,1,1,0,0,0]
n = len(binary_data)
X = [2*e-1 for e in binary_data]
S = fft(X)
M = [abs(s) for s in S[:n//2]]
T = sqrt(log(1/0.05) * n)
N0 = 0.95 * n / 2
N1 = 0
for m in M:
if m < T:
N1 += 1
d = (N1 - N0) / (sqrt(n * 0.95 * 0.05 / 4))
p_val = erfc(abs(d)/sqrt(2))
print(f'N0: {N0}\nN1: {N1}\nT: {T}\nd: {d}\np value: {p_val}')
该binary_data
列表被硬编码用于演示目的,取自上面链接的 NIST 文档第 2.6.8 节。变量名称遵循所述文档的命名。
当我运行这段代码时,我得到了结果
N0: 47.5
N1: 48
T: 17.30818382602285
d: 0.4588314677411235
p value: 0.6463551955394902
而不是第 2.6.8 节中显示的预期结果
N0: 47.5
N1: 46
d: -1.376494
p value: 0.168669
这意味着我在计算时在某处犯了错误N1
。我的问题是我不知道在哪里。我试图四处寻找这个测试的实现,但我只找到了这个,它返回的结果与我的代码完全相同。
我在哪里犯了错误?我是否在任何时候误解了参考文档,或者我是否滥用了任何导入的数学函数/库?