random --- 生成偽隨機數— Python 3.10.5 說明文件

文章推薦指數: 80 %
投票人數:10人

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---生成偽隨機數 |



請為這篇文章評分?