嗯,有一种方法,称为熵提取器,它允许从不完全随机的源中获取(好的)随机数。
如果您有三个独立但质量有些低(有偏差)的 RNG,您可以将它们组合成统一的源代码。
假设您有三个生成器,每个生成器都给您一个字节,那么统一输出将是
t = X*Y + Z
其中加法和乘法是在 GF(28) 有限域上完成的。
代码,Python
import numpy as np
import matplotlib.pyplot as plt
from pyfinite import ffield
def RNG(p):
return np.random.binomial(1, p) + \
np.random.binomial(1, p)*2 + \
np.random.binomial(1, p)*4 + \
np.random.binomial(1, p)*8 + \
np.random.binomial(1, p)*16 + \
np.random.binomial(1, p)*32 + \
np.random.binomial(1, p)*64 + \
np.random.binomial(1, p)*128
def muRNG(p):
X = RNG(p)
Y = RNG(p)
Z = RNG(p)
GF = ffield.FField(8)
return GF.Add(GF.Multiply(X, Y), Z)
N = 100000
hist = np.zeros(256, dtype=np.int32)
for k in range(0, N):
q = muRNG(0.7)
hist[q] += 1
x = np.arange(0, 256, dtype=np.int32)
fig, ax = plt.subplots()
ax.stem(x, hist, markerfmt=' ')
plt.show()
将生成字节分布图 - 对于 [0...256) 中的值,看起来是合理的统一。我可以找到提出这个想法的论文
只是为了说明,这是我们在没有熵提取的情况下收集字节时的样子,代码
...
q = RNG(0.7) # just byte value from bits with p=0.7
...
和图表