random --- 生成偽隨機數— Python 3.10.5 說明文件
文章推薦指數: 80 %
Mersenne Twister 是現存最廣泛被驗證的隨機數產生器之一,但是基於完全確定性,它並不適合所有目的,並且完全不適合加密目的。
該module 提供的函式實際上是 random.
瀏覽
索引
模組|
下一頁|
上一頁|
Python»
3.10.5Documentation»
Python標準函式庫(StandardLibrary)»
數值與數學模組»
random---生成偽隨機數
|
random---生成偽隨機數¶
原始碼:Lib/random.py
本章中所提及的module(模組)用來實現各種分佈的虛擬隨機數產生器。
對於整數,可以從範圍中進行均勻選擇。
對於序列,有一個隨機元素的均勻選擇,一個用來原地(in-place)產生隨機排列清單的函式,以及一個用來隨機採樣不替換的函式。
在實數線上,有一些函式用於處理均勻分佈、常態分佈(高斯分佈)、對數常態分佈、負指數分佈、gamma分佈和Beta分佈。
對於生成角度分佈,可以使用馮·米塞斯分佈(vonMisesdistribution)。
幾乎所有module函式都相依於基本函式random(),此函式在半開放範圍[0.0,1.0)內均勻地生成一個隨機float(浮點數)。
Python使用MersenneTwister(梅森旋轉演算法)作為核心的產生器,它產生53位元精度float,其週期為2**19937-1,透過C語言進行底層的實作既快速又支援執行緒安全(threadsafe)。
MersenneTwister是現存最廣泛被驗證的隨機數產生器之一,但是基於完全確定性,它並不適合所有目的,並且完全不適合加密目的。
該module提供的函式實際上是random.Randomclass(類別)中一個隱藏實例的綁定方法(boundmethod)。
你可以實例化自己的Random實例,以得到不共享狀態的產生器。
如果你想使用你自己設計的基本產生器,Random也可以進行子類別化(subclass):在這種情況下,要覆蓋random()、seed()、getstate()和setstate()的方式。
你也可以為新的產生器提供getrandbits()方法---這允許randrange()在任意大的範圍內產生選擇。
randommodule也提供了SystemRandomclass,使用系統函式os.urandom()從作業系統提供的來源產生隨機數。
警告
本章所提及的虛擬隨機數產生器不應該使用於安全目的。
有關安全性或加密用途,請參考secretsmodule。
也參考
M.MatsumotoandT.Nishimura,"MersenneTwister:A623-dimensionally
equidistributeduniformpseudorandomnumbergenerator",ACMTransactionson
ModelingandComputerSimulationVol.8,No.1,Januarypp.3--301998.
進位互補乘法(Complementary-Multiply-with-Carry)用法,可作為隨機數產生器的一個可相容替代方案,具有較長的週期和相對簡單的更新操作。
簿記函式(bookkeepingfunctions)¶
random.seed(a=None,version=2)¶
初始化隨機數產生器。
如果a被省略或為None,則使用當前系統時間。
如果隨機來源由作業系統提供,則使用它們而不是系統時間(有關可用性的詳細資訊,請參考os.urandom()函式)。
如果a為int(整數),則直接使用它。
如使用版本2(預設值),str、bytes或bytearray物件將轉換為int,並使用其所有位元。
若使用版本1(為復現於舊版本Python中產生隨機序列而提供),str和bytes的演算法會生成範圍更窄的種子(seed)。
3.2版更變:移至版本2方案,該方案使用字串種子中的所有位元。
3.9版後已棄用:將來,seed必須是以下型別之一:NoneType、int、float、str、bytes、bytearray。
random.getstate()¶
回傳一個物件,捕獲產生器的當前內部狀態。
此物件可以傳遞給setstate()以恢復狀態。
random.setstate(state)¶
state應該要從之前對getstate()的呼叫中獲得,並且以setstate()將產生器的內部狀態恢復到呼叫getstate()時的狀態。
回傳位元組的函式¶
random.randbytes(n)¶
產生n個隨機位元組。
此方法不應使用於產生安全性權杖(Token)。
請改用secrets.token_bytes()。
3.9版新加入.
回傳整數的函式¶
random.randrange(stop)¶
random.randrange(start,stop[,step])
從range(start,stop,step)中回傳一個隨機選擇的元素。
這等效於choice(range(start,stop,step)),但實際上並沒有構建範圍物件。
位置引數模式與range()的位置引數模式匹配。
不應使用關鍵字引數,因為函式可能會以不預期的方式使用它們。
3.2版更變:randrange()在產生均勻分佈的值方面更為複雜。
以前,它使用像int(random()*n)這樣的樣式,這可能會產生稍微不均勻的分佈。
3.10版後已棄用:非整數類型到等效整數的自動轉換已被棄用。
目前randrange(10.0)被無損轉換為randrange(10)。
將來,這將會引發TypeError。
3.10版後已棄用:對於非整數值,例如randrange(10.5)或randrange('10'),引發的例外將從ValueError改為TypeError。
random.randint(a,b)¶
回傳一個隨機整數N,使得a<=N<=b。
為randrange(a,b+1)的別名。
random.getrandbits(k)¶
回傳一個具有k個隨機位元的非負Python整數。
此方法會隨MersenneTwister產生器一起提供,一些其他的產生器也可能將其作為API的可選部分。
如果可用,getrandbits()使randrange()能夠處理任意大的範圍。
3.9版更變:此方法現在接受k為零。
回傳序列的函式¶
random.choice(seq)¶
從非空序列seq回傳一個隨機元素。
如果seq為空,則引發IndexError。
random.choices(population,weights=None,*,cum_weights=None,k=1)¶
回傳從population中重置取樣出的一個大小為k的元素list。
如果population為空,則引發IndexError。
如果指定了weights序列,則根據相對權重進行選擇。
另外,如果給定cum_weights序列,則根據累積權重進行選擇(可能使用itertools.accumulate()計算)。
例如,相對權重[10,5,30,5]等同於累積權重[10,15,45,50]。
在內部,相對權重在進行選擇之前會轉換為累積權重,因此提供累積權重可以節省工作。
如果既未指定weights也未指定cum_weights,則以相等的機率進行選擇。
如果提供了加權序列,則該序列的長度必須與population序列的長度相同。
它是一個TypeError來指定weights和cum_weights。
weights或cum_weights可以使用任何與random()所回傳的float值(包括整數、float和分數,但不包括小數)交互操作(interoperates)的數值類型。
權重假定為非負數和有限的。
如果所有權重均為零,則引發ValueError。
對於給定的種子,具有相等權重的choices()函式通常產生與重複呼叫choice()不同的序列。
choices()使用的演算法使用浮點院算來實現內部一致性和速度。
choice()使用的演算法預設為整數運算和重複選擇,以避免捨入誤差產生的小偏差。
3.6版新加入.
3.9版更變:如果所有權重均為零,則引發ValueError。
random.shuffle(x[,random])¶
將序列x原地(inplace)隨機打亂位置。
選擇性引數random是一個0引數函式,回傳一個在[0.0,1.0)之間的隨機float;預設情況下,這是函式random()。
要打亂一個不可變的序列並回傳一個新的被打亂的list(串列),請使用sample(x,k=len(x))。
請注意,即使對於較小的len(x),x的置換總數也會快速成長到大於大多數隨機數產生器的週期。
這意味著長序列的大多數置換永遠無法產生。
例如,長度為2080的序列是MersenneTwister隨機數產生器週期內可以容納的最大序列。
Deprecatedsinceversion3.9,willberemovedinversion3.11:選擇性參數random。
random.sample(population,k,*,counts=None)¶
回傳從母體序列或集合中選擇出的一個包含獨特元素、長度為k的list。
用於不重置的隨機取樣。
回傳包含母體元素的新清單,同時保持原始母體不變。
產生的清單按選擇順序排列,因此所有子切片也會是有效的隨機樣本。
這允許抽獎獲獎者(樣本)分為大獎和第二名獲獎者(子切片)。
母體成員不必是hashable或唯一的。
如果母體包含重複項,則每次出現都是樣本中可能出現的一個選擇。
可以一次指定一個重複元素,也可以使用可選的僅關鍵字counts參數指定重複元素。
例如sample(['red','blue'],counts=[4,2],k=5)等同於sample(['red','red','red','red','blue','blue'],k=5)。
若要從整數範圍中選擇範例,請使用range()物件作為引數。
這對於從大型母體中取樣特別快速且節省空間:sample(range(10000000),k=60)。
如果樣本大小大於母體大小,ValueError會被引發。
3.9版更變:新增counts參數。
3.9版後已棄用:將來,population必須是一個序列。
不再支援set的實例。
必須先將集合轉換為list或tuple,最好是按確定性順序,以便取樣是可復現的。
實數分布¶
以下函式產生特定的實數分佈。
函式參數以分佈方程中的對應變數命名,如常見的數學實踐所示;這些方程式中的大多數都可以在任意統計文本中找到。
random.random()¶
回傳範圍[0.0,1.0)中的下一個隨機浮點數。
random.uniform(a,b)¶
回傳一個隨機浮點數N,當a<=b時確保N為a<=N<=b、b0和beta>0。
回傳值的範圍介於0和1之間。
random.expovariate(lambd)¶
指數分佈。
lambd為1.0除以所需的平均數。
它應該不為零。
(該參數將被稱為"lambda",但這是Python中的保留字)如果lambd為正,則回傳值的範圍從0到正無窮大;如果lambd為負,則回傳值的範圍從負無窮大到0。
random.gammavariate(alpha,beta)¶
Gamma(伽瑪)分佈。
(不是Gamma函式!)參數的條件為alpha>0和beta>0。
Probabilitydistributionfunction(機率密度函式)是:
x**(alpha-1)*math.exp(-x/beta)
pdf(x)=--------------------------------------
math.gamma(alpha)*beta**alpha
random.gauss(mu,sigma)¶
常態分佈,也稱為高斯分佈。
mu是平均數,sigma是標準差。
這比下面定義的normalvariate()函式快一點。
多執行緒須注意:當兩個執行緒同時呼叫此函式時,它們可能會收到相同的傳回值。
這可以透過三種方式避免。
1)讓每個執行緒使用隨機數產生器的不同實例。
2)在所有呼叫周圍加鎖。
3)使用較慢但執行緒安全的normalvariate()函式代替。
random.lognormvariate(mu,sigma)¶
對數常態分佈。
如果你取此分佈的自然對數,你將獲得一個具有平均數mu和標準差sigma的常態分佈。
mu可以為任何值,並且sigma必須大於零。
random.normalvariate(mu,sigma)¶
常態分佈。
mu是平均數,sigma是標準差。
random.vonmisesvariate(mu,kappa)¶
mu是平均角度,以0到2*pi之間的弧度表示,kappa是濃度參數,必須大於或等於零。
如果kappa等於零,則此分佈在0到2*pi的範圍內將減小為均勻的隨機角度。
random.paretovariate(alpha)¶
Paretodistribution(柏拉圖分佈)。
alpha是形狀參數。
random.weibullvariate(alpha,beta)¶
Weibulldistribution(韋伯分佈)。
alpha是比例參數,beta是形狀參數。
替代產生器¶
classrandom.Random([seed])¶
實現random模組使用的預設偽隨機數產生器的class。
3.9版後已棄用:將來,seed必須是以下類型之一:NoneType、int、float、str、bytes、bytearray。
classrandom.SystemRandom([seed])¶
使用os.urandom()函式從作業系統提供的來源產生隨機數的Class。
並非在所有系統上都可用。
不依賴於軟體狀態,並且序列不可復現。
因此seed()方法沒有效果且被忽略。
如果呼叫getstate()和setstate()方法會引發NotImplementedError。
關於Reproducibility(復現性)的注意事項¶
有時,能夠重現偽隨機數產生器給出的序列很有用。
只要多執行緒未運行,透過重複使用種子值,同一序列就應該可以被復現。
大多數隨機module的演算法和seed設定函式在Python版本中可能會發生變化,但可以保證兩個方面不會改變:
如果增加了新的seed設定函式,則將提供向後相容的播種器(seeder)。
當相容的播種器被賦予相同的種子時,產生器的random()方法將持續產生相同的序列。
範例¶
基礎範例:
>>>random()#Randomfloat:0.0<=x<1.0
0.37444887175646646
>>>uniform(2.5,10.0)#Randomfloat:2.5<=x<=10.0
3.1800146073117523
>>>expovariate(1/5)#Intervalbetweenarrivalsaveraging5seconds
5.148957571865031
>>>randrange(10)#Integerfrom0to9inclusive
7
>>>randrange(0,101,2)#Evenintegerfrom0to100inclusive
26
>>>choice(['win','lose','draw'])#Singlerandomelementfromasequence
'draw'
>>>deck='acetwothreefour'.split()
>>>shuffle(deck)#Shufflealist
>>>deck
['four','two','ace','three']
>>>sample([10,20,30,40,50],k=4)#Foursampleswithoutreplacement
[40,10,50,30]
模擬:
>>>#Sixroulettewheelspins(weightedsamplingwithreplacement)
>>>choices(['red','black','green'],[18,18,2],k=6)
['red','green','black','black','red','black']
>>>#Deal20cardswithoutreplacementfromadeck
>>>#of52playingcards,anddeterminetheproportionofcards
>>>#withaten-value:ten,jack,queen,orking.
>>>dealt=sample(['tens','lowcards'],counts=[16,36],k=20)
>>>dealt.count('tens')/20
0.15
>>>#Estimatetheprobabilityofgetting5ormoreheadsfrom7spins
>>>#ofabiasedcointhatsettlesonheads60%ofthetime.
>>>deftrial():
...returnchoices('HT',cum_weights=(0.60,1.00),k=7).count('H')>=5
...
>>>sum(trial()foriinrange(10_000))/10_000
0.4169
>>>#Probabilityofthemedianof5samplesbeinginmiddletwoquartiles
>>>deftrial():
...return2_500<=sorted(choices(range(10_000),k=5))[2]<7_500
...
>>>sum(trial()foriinrange(10_000))/10_000
0.7958
統計bootstrapping(自助法)的範例,使用有重置的重新取樣來估計樣本平均數的信賴區間:
#http://statistics.about.com/od/Applications/a/Example-Of-Bootstrapping.htm
fromstatisticsimportfmeanasmean
fromrandomimportchoices
data=[41,50,29,37,81,30,73,63,20,35,68,22,60,31,95]
means=sorted(mean(choices(data,k=len(data)))foriinrange(100))
print(f'Thesamplemeanof{mean(data):.1f}hasa90%confidence'
f'intervalfrom{means[5]:.1f}to{means[94]:.1f}')
重新取樣排列測試的範例,來確定觀察到的藥物與安慰劑之間差異的統計學意義或p值:
#Examplefrom"StatisticsisEasy"byDennisShashaandMandaWilson
fromstatisticsimportfmeanasmean
fromrandomimportshuffle
drug=[54,73,53,70,73,68,52,65,65]
placebo=[54,51,58,44,55,52,42,47,58,46]
observed_diff=mean(drug)-mean(placebo)
n=10_000
count=0
combined=drug+placebo
foriinrange(n):
shuffle(combined)
new_diff=mean(combined[:len(drug)])-mean(combined[len(drug):])
count+=(new_diff>=observed_diff)
print(f'{n}labelreshufflingsproducedonly{count}instanceswithadifference')
print(f'atleastasextremeastheobserveddifferenceof{observed_diff:.1f}.')
print(f'Theone-sidedp-valueof{count/n:.4f}leadsustorejectthenull')
print(f'hypothesisthatthereisnodifferencebetweenthedrugandtheplacebo.')
模擬多伺服器佇列(queue)的到達時間與服務交付:
fromheapqimportheapify,heapreplace
fromrandomimportexpovariate,gauss
fromstatisticsimportmean,quantiles
average_arrival_interval=5.6
average_service_time=15.0
stdev_service_time=3.5
num_servers=3
waits=[]
arrival_time=0.0
servers=[0.0]*num_servers#timewheneachserverbecomesavailable
heapify(servers)
foriinrange(1_000_000):
arrival_time+=expovariate(1.0/average_arrival_interval)
next_server_available=servers[0]
wait=max(0.0,next_server_available-arrival_time)
waits.append(wait)
service_duration=max(0.0,gauss(average_service_time,stdev_service_time))
service_completed=arrival_time+wait+service_duration
heapreplace(servers,service_completed)
print(f'Meanwait:{mean(waits):.1f}Maxwait:{max(waits):.1f}')
print('Quartiles:',[round(q,1)forqinquantiles(waits)])
也參考
StatisticsforHackers是由JakeVanderplas製作的教學影片,僅使用幾個基本概念(包括模擬、取樣、洗牌、交叉驗證)進行統計分析。
EconomicsSimulation是由PeterNorvig對市場進行的模擬,顯示了該模組提供的許多工具和分佈(高斯、均勻、樣本、beta變數、選擇,三角形、隨機數)的有效使用。
機率的具體介紹(使用Python)為PeterNorvig的教學課程,涵蓋了機率理論的基礎知識與如何模擬以及使用Python執行數據分析。
使用方案¶
預設的random()回傳0.0≤x<1.0範圍內2⁻⁵³的倍數。
所有數字都是均勻分佈的,並且可以完全表示為Pythonfloat。
但是,該間隔中的許多其他可表示的float不是可能的選擇。
例如0.05954861408025609不是2⁻⁵³的整數倍。
以下範例採用不同的方法。
間隔中的所有float都是可能的選擇。
尾數來自2⁵²≤尾數<2⁵³範圍內的整數均勻分佈。
指數來自幾何分佈,其中小於-53的指數的出現頻率是下一個較大指數的一半。
fromrandomimportRandom
frommathimportldexp
classFullRandom(Random):
defrandom(self):
mantissa=0x10_0000_0000_0000|self.getrandbits(52)
exponent=-53
x=0
whilenotx:
x=self.getrandbits(32)
exponent+=x.bit_length()-32
returnldexp(mantissa,exponent)
Class中的所有實數分佈都將使用新方法:
>>>fr=FullRandom()
>>>fr.random()
0.05954861408025609
>>>fr.expovariate(0.25)
8.87925541791544
該範例在概念上等效於一種演算法,該演算法從0.0≤x<1.0範圍內2⁻¹⁰⁷⁴的所有倍數中進行選擇。
這些數字都是均勻分佈的,但大多數必須向下捨入到最接近的可表示的Pythonfloat。
(2⁻¹⁰⁷⁴是最小為正的非正規化float,等於math.ulp(0.0))
也參考
產生偽隨機浮點值AllenB.Downey的一篇論文描述了產生比通常由random()產生的float更fine-grained(細粒的)的方法。
目录
random---生成偽隨機數
簿記函式(bookkeepingfunctions)
回傳位元組的函式
回傳整數的函式
回傳序列的函式
實數分布
替代產生器
關於Reproducibility(復現性)的注意事項
範例
使用方案
上個主題
fractions---分数
下個主題
statistics---數學統計函式
此頁面
回報錯誤
顯示原始碼
瀏覽
索引
模組|
下一頁|
上一頁|
Python»
3.10.5Documentation»
Python標準函式庫(StandardLibrary)»
數值與數學模組»
random---生成偽隨機數
|
延伸文章資訊
- 1伪随机数生成器 - 维基百科
伪随机数生成器(pseudo random number generator,PRNG),又被称为确定性随机比特生成器(deterministic random bit generator,DR...
- 2簡介亂數 - iT 邦幫忙
密碼學安全偽隨機性,當有一部分的樣本與演算法時,依然無法推測下一個亂數為何。 ... 僞隨機數產生器(PRNG,全名為Pseudo-random Number Generator):滿足第一個 ...
- 3偽隨機數生成器_百度百科
偽隨機數生成器,隨機數生成器(random number generator)通過算法、物理訊號、環境噪聲等來產生似乎沒有關聯性的數列的方法或裝置。
- 4伪随机数生成器介绍 - CTF Wiki
伪随机数生成器(pseudorandom number generator,PRNG),又称为确定性随机位生成器(deterministic random bit generator,DRBG)...
- 5密碼學安全偽亂數生成器 - Wikiwand
密碼學安全偽亂數生成器(亦作密碼學偽亂數生成器,英文:Cryptographically secure pseudo-random number generator,通稱CSPRNG),是一種能...