python中的两种随机数产生机制

(https://www.cnblogs.com/lzxwalex/p/6880748.html)

随机种子:

随机种子(Random Seed)是计算机专业术语,一种以随机数作为对象的以真随机数(种子)为初始条件的随机数。

一般计算机的随机数都是伪随机数,以一个种子作为初始条件,然后用一定的算法不停迭代产生随机数。

 

伪随机数:

因为真随机涉及到了物理的量子.故本⽂只讨论伪随机数的⽣成⽅法。

在python 中的random库中,会用到如randint之类的⽅法来生成一定范围内的随机数.这之中主要用到的方法步骤为

->指定一个特定的seed种子;

->根据seed再通过特定的随机数产生方法,就可以做到在[0,1]这个范围中取到随机分布的随机数;

->然后经过一定的变换,就可以得到一定范围内的随机数了.

伪随机数产生方法:

  • 线性同余方法
  • 平方取中方法
  • 梅森旋转随机生成法
  • BOX-MULLER法

随机数的计算方法在不同的计算机中是不同的,即使在相同的计算机中安装的不同的操作系统中也是不同的。

随机数产生方法好坏的判定:

判定标准和判断工具.比如像NIST测试方法,TestU01的测试工具等,此处给出德联信息安全工作室的一套方法。

  1. 包含相同随机数序列的概率很低。
  2. 根据指定的统计检验区别于“真随机数”的数字序列。
  3. 它不可能被任何人能够通过计算得到,或以其他的方法进行猜测,得到任何给定的一个子序列,以及任何工作中产生的一切序列中的值,以及迭代器的工作状态。
  4. 对于任何目的而言,任何人不能从随机数生成器的内部状态计算或猜测得到序列中的任何一个之前的数字/序列以及任何之前的随机数的状态。

 

方法介绍:

  1. 经典的随机数产生方法为是线性同余法,即Linear Congruence Generator (LCG),由Lehmer于1951年提出。(同余:对于两个整数A、B,如果它们同时除以一个自然数M的余数相同,就说A、B对于模M同余,A≡B mod M。)

            线性同余发生器是用不连续的、分段的线性方程产生伪随机数序列的算法。LCG的定义:

 

其中

X   是随机数序列

m   m > 0,模

a   0 < a < m ,乘子

c   0 ≤ c < m ,增量,即偏移量

X0   0 ≤ X0 < m ,开始值,通常叫做“种子”seed

 

* 模的选取:对于随机数的⽣成⽽⾔,随机数序列周期越长, 它就越能够在[0, 1]上均匀分布及相互独⽴。m 越⼤周期就越大,所以使 m 接近于计算机能表示的最⼤的整数。

* 乘子的选取:对于 m 的任何一个质因子p,a-1 能被 P 整除,且如果 4 是 m 的因子,则 a 除以4余1。

* 增量的选取:增量 c 和 m 互质

 

缺点:周期太短、如果被知道一定长度的序列就能破解出所有的随机数生成序列

 
程序:linear_congruence.py
#import
from time import time,clock
#define
m = 2 ** 32
a = 1103515245
c = 12345
def LCG(seed):
    seed = (a * seed + c) % m
    return seed / float(m-1)
def main():
    br = input("请输⼊随机数产生的范围(⽤,隔开):")
    mi = eval(br.split(',')[0])
    ma = eval(br.split(',')[1])
    seed = time()
    rd = LCG(seed)
    print(rd)
    ourd = int((ma-mi)*rd) + mi
    print(ourd)
    print("随机⽣成的数字是:{}".format(ourd))
main()
  1. 2.  平方取中法
  • 选择一个m位数N(本例为当前时间戳),作为SEED种子,做平⽅运算;
  • 判断N* N的长度,若小于2m,在最前面补0;
  • 在这个N*N的数中选中间m个位的数作为随机数.

 

缺点:周期很短、分布并不不均匀

 

程序:middle_square.py
#平⽅方取中
from time import time
def rander(seed,n):
    if n ==1:
        return 0
    seed = int(seed)
    length = len(str(seed))
    seed = int(seed ** 2 / pow(10,(length/2))) % int(pow(10.0,length))
    '''
    seed = (seed^2 / 10^(length/2)) % 10^length
    '''
    print("n= %d,seed = %d" % (n, seed))
    rander(seed,n-1)
def main():
    seed = time()
    print("seed =",seed)
    rander(seed,100)
main()

 

posted @ 2018-11-20 17:03  没有比脚更长的路  阅读(6094)  评论(0编辑  收藏  举报