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()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM