1 . 概念
1.1 真、偽隨機數
大部分的計算機語言都會提供 API 生成隨機數,此類 API 稱為隨機數生成器。
計算機可以用隨機數模擬現實世界中的各種隨機概率問題,沒有隨機生成器的程式語言不是“好語言”。
什麼是真隨機數?
現實世界中的隨機數:比如擲錢幣、骰子、轉輪、使用電子元件的噪音、核裂變等等。
計算機通過硬體技術摸擬現實世界中這種物理現象所生成的隨機數,我們稱其為真隨機數。 這樣的隨機數生成器叫做物理性隨機數生成器。生成真隨機數對計算機的硬體技術要求較高。
真正隨機數的特點:不可預測。
如在擲硬幣時,你無法真正預測到下一次硬幣的面向。
什麼是偽隨機數?
由演算法摸擬生成的隨機數稱其為偽隨機數。計算機程式語言中所生成的隨機數基本上都是偽隨機數。
偽隨機數的特點:既然是由演算法模擬的,雖然在一個較短的週期內是無法預測的,在一個較長的週期內的隨機數具有可預測性。
1.2 隨機數種子
生成偽隨機數時,需要設定隨機種子,種子作用就是在隨機數的生成演算法裡注入一個動態變化量。
比如說使用系統的當前時間做隨機種子,隨機演算法就可以在時間變化的基礎上生成隨機性更大的隨機數。但是,如果不是在毫秒級別下生成隨機數,同一時間點下所生成的大量隨機數就有可能出現相等的情況。
選擇種子時,可以考慮綜合多維度的變化值進行運算。如在 UNIX 系統中,將系統時間、連入WIFI、甚至按下的鍵盤次數都量化為了seed。
參考指標越多,偽隨機數就越接近真正的隨機生成。
2. Python random 模組
random 模組實現了各種分佈的偽隨機數生成器。因為完全確定性,它不適用於所有目的,並且完全不適合加密目的。不應將此模組的偽隨機生成器用於安全目的。 有關安全性或加密用途,可使用 Python 中的 secrets 模組。
使得之前需要匯入 random 模組
import random
2.1 隨機模組的方法
- 初始化隨機種子
random.seed(a=None, version=2)
-
如果 a 被省略或為
None
,則使用當前系統時間做隨機種子。 -
如果作業系統提供隨機源,則使用它們而不是系統時間。
-
如果 a 是 int 型別,則直接使用。
當設定隨機種子是一個常量,則每一次隨機數是固定的。
import random #設定隨機種子是一個 int 常量 random.seed(10) print(random.random()) #設定隨機種子是一個 int 常量 random.seed(10) print(random.random()) #設定隨機種子是一個 int 常量 random.seed(10) print(random.random())
輸出結果:
0.5714025946899135 0.5714025946899135 0.5714025946899135
- 從一個數字範圍內產生隨機數字
random.randrange(start, stop[, step])
從 range(start, stop, step) 返回一個隨機選擇的元素。
這相當於 choice(range(start, stop, step)),但實際上並沒有構建一個 range 物件。
- 返回隨機整數
random.randint(a, b)
相當於 randrange(a, b+1)
結果 N 滿足: a <= N <= b
- 從非空序列 seq 返回一個隨機元素。 如果 seq 為空,則引發 IndexError 異常。
random.choice(seq)
import random
lst = [5, 3, 90, 12, 4, 6]
r = random.choice(lst)
print(r)
每一次執行會從列表中隨機獲得一個數字。
- 將序列 x 隨機打亂
andom.shuffle(x[, random])
可選引數 random 是一個無引數函式,在 [0.0, 1.0) 中返回隨機浮點數;預設情況下,這是函式 random()
import random
lst = [5.0, 3.0, 90.0, 12.0, 4.0, 6.0]
#使用 random.random 函式
random.shuffle(lst, random.random)
print(lst)
#輸出結果
[3.0, 90.0, 6.0, 12.0, 5.0, 4.0]
#----------------------------------
def my_random():
return float(random.randint(0, 1))
lst = [5.0, 3.0, 90.0, 12.0, 4.0, 6.0]
#使用使用者自定義函式
random.shuffle(lst, my_random)
print(lst)
- 返回從總體序列或集合中選擇的唯一元素的 k 長度列表。 用於無重複的隨機抽樣。
random.sample(population, k, *, counts=None)
- 返回 [0.0, 1.0) 範圍內的下一個隨機浮點數。
random.random()
- 返回一個隨機浮點數 N
random.uniform(a, b)
取決於等式 a + (b-a) * random() 中的浮點舍入,終點 b 可以包括或不包括在該範圍內。
結果 N 滿足:當
a <= b
時a <= N <= b
,當b < a
時b <= N <= a
。
更多方法可查閱官方文件。
3. 不可預測之美
3.1 隨機彩色點
解題思路: 可結合 turtle 模組繪製,隨機小海龜出現的位置就可以了
import random
import turtle
colors = ["red", "blue", "green", "gray", "orange"]
for i in range(100):
turtle.penup()
x = random.randint(-300, 300)
y = random.randint(-300, 300)
turtle.goto(x, y)
turtle.pendown()
turtle.dot(20, colors[i % 5])
turtle.done()
3.2 求 π 的值
概率法又稱為蒙特卡羅法,是一種非常重要的數值計算方法。
該方法是以概率和統計理論方法為基礎的一種計算方法。將所求解的問題同一定的概率模型相聯絡,用計算機實現統計模擬或抽樣,以獲得問題的近似解。
假設有一個半徑為 1 的圓,如圖所示,則圖中陰影部分(1/4圓)的面積就等於值的1/4。通過概率法計算出陰影部分的面積,也就得到了π 值的 1/4,將陰影部分面積乘以 4 即可得到 π 的近似值。
求解思路
-
利用隨機函式產生橫座標的值 x 和縱座標的值 y(這兩個值都應在0~1)
-
判斷由這兩個隨機數構成的點是否位於1/4圓的區域內(陰影部分),若該點位於陰影區域內則進行計數。
-
不斷產生新的點,由於隨機函式生成的點座標有一定的均勻性,當生成的點足夠多時,就可得到陰影內和陰影外點的近似均勻分佈。
-
最後用在陰影內的點的數量除以總的點數,即可得到近似的陰影面積,也就得到了一個的1/4的近似值。
import random
i, n, s = 0, 0, 0
x, y = 0.0, 0.0
n = int(input("輸入點的數量:"))
random.seed()
for i in range(n):
x = random.random()
y = random.random()
if (x * x + y * y) <= 1:
s += 1
print("PI=%f\n", 4 * s / n)
輸出結果:
輸入點的數量:9000000
PI= 3.141477777777778
輸入的點數量越多,得到的 PI 的近似值就會越精確。
4 . 總結
隨機數可以完美地模擬真實世界裡的各種概率或隨機事件。python 的隨機數生成除了可以使用 random 模組外,還可以使用 numpy 庫中所提供的方法。