最近科研的需要,需要测试二进制序列的随机性
找遍所有内网都没有找到自己合适的代码,网上很多都是讲解自己怎么去下载和安装sts-2.1.2的开发包,于是我也是一开始就入坑了,之前也是写了一篇比较完整的工具包的下载和安装的教程,点击打开链接,但是如果你按照我的安装步骤的话,成功安装肯定是没有问题的,但是你的使用就会出现各种各样的问题:
比如我在使用的过程中遇到的问题有:首先,就是经常出现UNDERFLOW的情况,这种情况下,一般都是因为数据量不够大的情况下造成的,所以如果你用过,你就会发现,想要测试15项的内容,大约你需要1GBit,这对于我们正常的情况下,是非常难的,根本达不到这个数据量,没错,肯定有的人会说,你可以不测试那么多的数据量啊 ,你可以测试部分的测试项啊,我也想啊,但是网上根本没有发现怎么使用,单独测试,而不是使用15项
我按照他的步骤,每次单独测试的时候总是会出现下面的情况,(我不知道你们有没有遇到)
看这个提示:如果你不想测试所有的项,请输入0,否则输入1.
然后我就输入0
从这里开始,无论你输入0还是1,都是没有响应了。我一直也没有找到任何解决的办法,如果有人知道,请留言交流。
但是又因为迫于科研的压力,还是要解决这个事情,这个是NIST的官方文档
参考开发文档,和国外大牛写的代码:整理并编写python如下:
这里把15个测试项都单独的编写了一个可以运行的python代码:
先看一下我的结果图:有两项不pass,13项success、
第一个是:
cumulative_sums_test
import math #from scipy.special import gamma, gammainc, gammaincc from gamma_functions import * #import scipy.stats def normcdf(n): return 0.5 * math.erfc(-n * math.sqrt(0.5)) def p_value(n,z): sum_a = 0.0 startk = int(math.floor((((float(-n)/z)+1.0)/4.0))) endk = int(math.floor((((float(n)/z)-1.0)/4.0))) for k in range(startk,endk+1): c = (((4.0*k)+1.0)*z)/math.sqrt(n) #d = scipy.stats.norm.cdf(c) d = normcdf(c) c = (((4.0*k)-1.0)*z)/math.sqrt(n) #e = scipy.stats.norm.cdf(c) e = normcdf(c) sum_a = sum_a + d - e sum_b = 0.0 startk = int(math.floor((((float(-n)/z)-3.0)/4.0))) endk = int(math.floor((((float(n)/z)-1.0)/4.0))) for k in range(startk,endk+1): c = (((4.0*k)+3.0)*z)/math.sqrt(n) #d = scipy.stats.norm.cdf(c) d = normcdf(c) c = (((4.0*k)+1.0)*z)/math.sqrt(n) #e = scipy.stats.norm.cdf(c) e = normcdf(c) sum_b = sum_b + d - e p = 1.0 - sum_a + sum_b return p def cumulative_sums_test(bits): n = len(bits) # Step 1 x = list() # Convert to +1,-1 for bit in bits: #if bit == 0: x.append((bit*2)-1) # Steps 2 and 3 Combined # Compute the partial sum and records the largest excursion. pos = 0 forward_max = 0 for e in x: pos = pos+e if abs(pos) > forward_max: forward_max = abs(pos) pos = 0 backward_max = 0 for e in reversed(x): pos = pos+e if abs(pos) > backward_max: backward_max = abs(pos) # Step 4 p_forward = p_value(n, forward_max) p_backward = p_value(n,backward_max) success = ((p_forward >= 0.01) and (p_backward >= 0.01)) plist = [p_forward, p_backward] if success: print ("PASS") else: print ("FAIL: Data not random") return (success, None, plist) bits=[1,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1,1,1,1,1, 0,1,1,1,1,1,0,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0, 0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0,0,0,0,1,0,1,0, 0,1,1,0,0,0,1,1,1,0,1,0,0,0,0,1,0,0,1,0,1,0,1,0,0,1,1, 0,0,0,1,1,0,1,0,1,1,1,0,0,1,1,1,1,1,0,0,0] if __name__ == "__main__": #bits = [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] success, _, plist = cumulative_sums_test(bits) print ("success =",success) print ("plist = ",plist)第二个是:maurers_universal_test
import math def pattern2int(pattern): l = len(pattern) n = 0 for bit in (pattern): n = (n << 1) + bit return n def maurers_universal_test(bits,patternlen=None, initblocks=None): n = len(bits) # Step 1. Choose the block size if patternlen != None: L = patternlen else: ns = [904960,2068480,4654080,10342400, 22753280,49643520,107560960, 231669760,496435200,1059061760] L = 6 if n < 387840: print ("Error. Need at least 387840 bits. Got %d." % n) exit() for threshold in ns: if n >= threshold: L += 1 # Step 2 Split the data into Q and K blocks nblocks = int(math.floor(n/L)) if initblocks != None: Q = initblocks else: Q = 10*(2**L) K = nblocks - Q # Step 3 Construct Table nsymbols = (2**L) T=[0 for x in range(nsymbols)] # zero out the table for i in range(Q): # Mark final position of pattern = bits[i*L:(i+1)*L] # each pattern idx = pattern2int(pattern) T[idx]=i+1 # +1 to number indexes 1..(2**L)+1 # instead of 0..2**L # Step 4 Iterate sum = 0.0 for i in range(Q,nblocks): pattern = bits[i*L:(i+1)*L] j = pattern2int(pattern) dist = i+1-T[j] T[j] = i+1 sum = sum + math.log(dist,2) print (" sum =", sum) # Step 5 Compute the test statistic fn = sum/K print (" fn =",fn) # Step 6 Compute the P Value # Tables from https://static.aminer.org/pdf/PDF/000/120/333/ # a_universal_statistical_test_for_random_bit_generators.pdf ev_table = [0,0.73264948,1.5374383,2.40160681,3.31122472, 4.25342659,5.2177052,6.1962507,7.1836656, 8.1764248,9.1723243,10.170032,11.168765, 12.168070,13.167693,14.167488,15.167379] var_table = [0,0.690,1.338,1.901,2.358,2.705,2.954,3.125, 3.238,3.311,3.356,3.384,3.401,3.410,3.416, 3.419,3.421] # sigma = math.sqrt(var_table[L]) mag = abs((fn - ev_table[L])/((math.sqrt(var_table[L]))*math.sqrt(2))) P = math.erfc(mag) success = (P >= 0.01) return (success, P, None) if __name__ == "__main__": #bits = [0,1,0,1,1,0,1,0,0,1,1,1,0,1,0,1,0,1,1,1] bits=[1,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1,1,1,1,1, 0,1,1,1,1,1,0,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0, 0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0,0,0,0,1,0,1,0, 0,1,1,0,0,0,1,1,1,0,1,0,0,0,0,1,0,0,1,0,1,0,1,0,0,1,1, 0,0,0,1,1,0,1,0,1,1,1,0,0,1,1,1,1,1,0,0,0] success, p, _ = maurers_universal_test(bits, patternlen=2, initblocks=4) print ("success =",success) print ("p = ",p)
这个好没效率,15项的代码太多了,等我把资源上传到csdn吧,等审核通过,我再来附链接。
下载链接:点击打开链接