源碼:?Lib/random.py
該模塊實現(xiàn)了各種分布的偽隨機數(shù)生成器。
對于整數(shù)柒啤,從范圍中有統(tǒng)一的選擇倦挂。 對于序列,存在隨機元素的統(tǒng)一選擇担巩、用于生成列表的隨機排列的函數(shù)方援、以及用于隨機抽樣而無需替換的函數(shù)。
在實數(shù)軸上涛癌,有計算均勻犯戏、正態(tài)(高斯)窥浪、對數(shù)正態(tài)、負(fù)指數(shù)笛丙、伽馬和貝塔分布的函數(shù)漾脂。 為了生成角度分布,可以使用 von Mises 分布胚鸯。
幾乎所有模塊函數(shù)都依賴于基本函數(shù)?random()?骨稿,它在半開放區(qū)間 [0.0,1.0) 內(nèi)均勻生成隨機浮點數(shù)。 Python 使用 Mersenne Twister 作為核心生成器姜钳。 它產(chǎn)生 53 位精度浮點數(shù)坦冠,周期為 2**19937-1 ,其在 C 中的底層實現(xiàn)既快又線程安全哥桥。 Mersenne Twister 是現(xiàn)存最廣泛測試的隨機數(shù)發(fā)生器之一辙浑。 但是,因為完全確定性拟糕,它不適用于所有目的判呕,并且完全不適合加密目的。
這個模塊提供的函數(shù)實際上是?random.Random?類的隱藏實例的綁定方法送滞。 你可以實例化自己的?Random?類實例以獲取不共享狀態(tài)的生成器侠草。
如果你想使用自己設(shè)計的不同基礎(chǔ)生成器,類?Random?也可以作為子類:在這種情況下犁嗅,重載?random()?边涕、?seed()?、?getstate()?以及?setstate()?方法褂微」︱眩可選地,新生成器可以提供?getrandbits()?方法——這允許?randrange()?在任意大的范圍內(nèi)產(chǎn)生選擇宠蚂。
random?模塊還提供?SystemRandom?類式撼,它使用系統(tǒng)函數(shù)?os.urandom()?從操作系統(tǒng)提供的源生成隨機數(shù)。
警告
不應(yīng)將此模塊的偽隨機生成器用于安全目的肥矢。 有關(guān)安全性或加密用途端衰,請參閱?secrets?模塊叠洗。
參見
M. Matsumoto and T. Nishimura, “Mersenne Twister: A 623-dimensionally equidistributed uniform pseudorandom number generator”, ACM Transactions on Modeling and Computer Simulation Vol. 8, No. 1, January pp.3–30 1998.
Complementary-Multiply-with-Carry recipe?用于兼容的替代隨機數(shù)發(fā)生器甘改,具有長周期和相對簡單的更新操作。
簿記功能
random.seed(a=None,?version=2)
初始化隨機數(shù)生成器灭抑。
如果?a?被省略或為?None?十艾,則使用當(dāng)前系統(tǒng)時間。 如果操作系統(tǒng)提供隨機源腾节,則使用它們而不是系統(tǒng)時間(有關(guān)可用性的詳細(xì)信息忘嫉,請參閱?os.urandom()?函數(shù))荤牍。
如果?a?是 int 類型,則直接使用庆冕。
對于版本2(默認(rèn)的)康吵,str?、?bytes?或?bytearray?對象轉(zhuǎn)換為?int?并使用它的所有位访递。
對于版本1(用于從舊版本的Python再現(xiàn)隨機序列)晦嵌,用于?str?和?bytes?的算法生成更窄的種子范圍。
在 3.2 版更改:?已移至版本2方案拷姿,該方案使用字符串種子中的所有位惭载。
random.getstate()
返回捕獲生成器當(dāng)前內(nèi)部狀態(tài)的對象。 這個對象可以傳遞給?setstate()?來恢復(fù)狀態(tài)响巢。
random.setstate(state)
state?應(yīng)該是從之前調(diào)用?getstate()?獲得的描滔,并且?setstate()?將生成器的內(nèi)部狀態(tài)恢復(fù)到?getstate()?被調(diào)用時的狀態(tài)。
random.getrandbits(k)
返回帶有?k?位隨機的Python整數(shù)踪古。 此方法隨 MersenneTwister 生成器一起提供含长,其他一些生成器也可以將其作為API的可選部分提供。 如果可用伏穆,getrandbits()?啟用?randrange()?來處理任意大范圍茎芋。
整數(shù)用函數(shù)
random.randrange(stop)random.randrange(start,?stop[,?step])
從?range(start,?stop,?step)?返回一個隨機選擇的元素。 這相當(dāng)于?choice(range(start,?stop,?step))?蜈出,但實際上并沒有構(gòu)建一個 range 對象田弥。
位置參數(shù)模式匹配?range()?。不應(yīng)使用關(guān)鍵字參數(shù)铡原,因為該函數(shù)可能以意外的方式使用它們偷厦。
在 3.2 版更改:?randrange()?在生成均勻分布的值方面更為復(fù)雜。 以前它使用了像``int(random()*n)``這樣的形式燕刻,它可以產(chǎn)生稍微不均勻的分布只泼。
random.randint(a,?b)
返回隨機整數(shù)?N?滿足?a?<=?N?<=?b。相當(dāng)于?randrange(a,?b+1)卵洗。
序列用函數(shù)
random.choice(seq)
從非空序列?seq?返回一個隨機元素请唱。 如果?seq?為空,則引發(fā)?IndexError过蹂。
random.choices(population,?weights=None,?*,?cum_weights=None,?k=1)
從*population*中選擇替換十绑,返回大小為?k?的元素列表。 如果?population?為空酷勺,則引發(fā)?IndexError本橙。
如果指定了?weight?序列,則根據(jù)相對權(quán)重進行選擇脆诉。 或者甚亭,如果給出?cum_weights?序列贷币,則根據(jù)累積權(quán)重(可能使用?itertools.accumulate()?計算)進行選擇。 例如亏狰,相對權(quán)重``[10, 5, 30, 5]``相當(dāng)于累積權(quán)重``[10, 15, 45, 50]``役纹。 在內(nèi)部,相對權(quán)重在進行選擇之前會轉(zhuǎn)換為累積權(quán)重暇唾,因此提供累積權(quán)重可以節(jié)省工作量字管。
如果既未指定?weight?也未指定?cum_weights?,則以相等的概率進行選擇信不。 如果提供了權(quán)重序列嘲叔,則它必須與?population?序列的長度相同。 一個?TypeError?指定了?weights?和*cum_weights*抽活。
weights?或?cum_weights?可以使用任何與?random()?返回的?float?值互操作的數(shù)值類型(包括整數(shù)硫戈,浮點數(shù)和分?jǐn)?shù)但不包括十進制小數(shù))。
3.6 新版功能.
random.shuffle(x[,?random])
將序列?x?隨機打亂位置下硕。
可選參數(shù)?random?是一個0參數(shù)函數(shù)丁逝,在 [0.0, 1.0) 中返回隨機浮點數(shù);默認(rèn)情況下梭姓,這是函數(shù)?random()?霜幼。
要改變一個不可變的序列并返回一個新的打亂列表,請使用``sample(x, k=len(x))``誉尖。
請注意罪既,即使對于小的?len(x),x?的排列總數(shù)也可以快速增長铡恕,大于大多數(shù)隨機數(shù)生成器的周期琢感。 這意味著長序列的大多數(shù)排列永遠(yuǎn)不會產(chǎn)生。 例如探熔,長度為2080的序列是可以在 Mersenne Twister 隨機數(shù)生成器的周期內(nèi)擬合的最大序列驹针。
random.sample(population,?k)
返回從總體序列或集合中選擇的唯一元素的?k?長度列表。 用于無重復(fù)的隨機抽樣诀艰。
返回包含來自總體的元素的新列表柬甥,同時保持原始總體不變。 結(jié)果列表按選擇順序排列其垄,因此所有子切片也將是有效的隨機樣本苛蒲。 這允許抽獎獲獎?wù)撸颖荆┍粍澐譃榇螵労偷诙@勝者(子切片)。
總體成員不必是?hashable?或 unique 捉捅。 如果總體包含重復(fù)撤防,則每次出現(xiàn)都是樣本中可能的選擇虽风。
要從一系列整數(shù)中選擇樣本棒口,請使用?range()?對象作為參數(shù)寄月。 對于從大量人群中采樣,這種方法特別快速且節(jié)省空間:sample(range(10000000),?k=60)?无牵。
如果樣本大小大于總體大小漾肮,則引發(fā)?ValueError?。
實值分布
以下函數(shù)生成特定的實值分布茎毁。如常用數(shù)學(xué)實踐中所使用的那樣, 函數(shù)參數(shù)以分布方程中的相應(yīng)變量命名;大多數(shù)這些方程都可以在任何統(tǒng)計學(xué)教材中找到克懊。
random.random()
返回 [0.0, 1.0) 范圍內(nèi)的下一個隨機浮點數(shù)。
random.uniform(a,?b)
返回一個隨機浮點數(shù)?N?七蜘,當(dāng)?a?<=?b?時?a?<=?N?<=?b?谭溉,當(dāng)?b?<?a?時?b?<=?N?<=?a?。
取決于等式?a?+?(b-a)?*?random()?中的浮點舍入橡卤,終點?b?可以包括或不包括在該范圍內(nèi)扮念。
random.triangular(low,?high,?mode)
返回一個隨機浮點數(shù)?N?,使得?low?<=?N?<=?high?并在這些邊界之間使用指定的?mode?碧库。?low?和?high?邊界默認(rèn)為零和一柜与。?mode?參數(shù)默認(rèn)為邊界之間的中點,給出對稱分布嵌灰。
random.betavariate(alpha,?beta)
Beta 分布弄匕。 參數(shù)的條件是?alpha?>?0?和?beta?>?0。 返回值的范圍介于 0 和 1 之間沽瞭。
random.expovariate(lambd)
指數(shù)分布迁匠。?lambd?是 1.0 除以所需的平均值,它應(yīng)該是非零的驹溃。 (該參數(shù)本應(yīng)命名為 “l(fā)ambda” 柒瓣,但這是 Python 中的保留字。)如果?lambd?為正吠架,則返回值的范圍為 0 到正無窮大芙贫;如果?lambd?為負(fù),則返回值從負(fù)無窮大到 0傍药。
random.gammavariate(alpha,?beta)
Gamma 分布磺平。 (?不是?gamma 函數(shù)! ) 參數(shù)的條件是?alpha?>?0?和?beta?>?0拐辽。
概率分布函數(shù)是:
????????? x**(alpha-1)*math.exp(-x/beta)
pdf(x)=?--------------------------------------
??????????? math.gamma(alpha)*beta**alpha
random.gauss(mu,?sigma)
高斯分布拣挪。?mu?是平均值,sigma?是標(biāo)準(zhǔn)差俱诸。 這比下面定義的?normalvariate()?函數(shù)略快菠劝。
random.lognormvariate(mu,?sigma)
對數(shù)正態(tài)分布。 如果你采用這個分布的自然對數(shù)睁搭,你將得到一個正態(tài)分布赶诊,平均值為?mu?和標(biāo)準(zhǔn)差為?sigma?笼平。?mu?可以是任何值,sigma?必須大于零舔痪。
random.normalvariate(mu,?sigma)
正態(tài)分布寓调。?mu?是平均值,sigma?是標(biāo)準(zhǔn)差锄码。
random.vonmisesvariate(mu,?kappa)
馮·米塞斯(von Mises)分布夺英。?mu?是平均角度,以弧度表示滋捶,介于0和 2*pi?之間痛悯,kappa?是濃度參數(shù),必須大于或等于零重窟。 如果?kappa?等于零灸蟆,則該分布在 0 到 2*pi?的范圍內(nèi)減小到均勻的隨機角度。
random.paretovariate(alpha)
帕累托分布亲族。?alpha?是形狀參數(shù)炒考。
random.weibullvariate(alpha,?beta)
威布爾分布。?alpha?是比例參數(shù)霎迫,beta?是形狀參數(shù)斋枢。
替代生成器
class?random.SystemRandom([seed])
使用?os.urandom()?函數(shù)的類,用從操作系統(tǒng)提供的源生成隨機數(shù)知给。 這并非適用于所有系統(tǒng)瓤帚。 也不依賴于軟件狀態(tài),序列不可重現(xiàn)涩赢。 因此戈次,seed()?方法沒有效果而被忽略。?getstate()?和?setstate()?方法如果被調(diào)用則引發(fā)?NotImplementedError筒扒。
關(guān)于再現(xiàn)性的說明
有時能夠重現(xiàn)偽隨機數(shù)生成器給出的序列是有用的怯邪。 通過重新使用種子值,只要多個線程沒有運行花墩,相同的序列就可以在兩次不同運行之間重現(xiàn)悬秉。
大多數(shù)隨機模塊的算法和種子函數(shù)都會在 Python 版本中發(fā)生變化,但保證兩個方面不會改變:
如果添加了新的播種方法冰蘑,則將提供向后兼容的播種機和泌。
當(dāng)兼容的播種機被賦予相同的種子時,生成器的?random()?方法將繼續(xù)產(chǎn)生相同的序列祠肥。
例子和配方
基本示例:
>>>random()????????????????????????????# Random float:? 0.0 <= x < 1.0
0.37444887175646646
>>>uniform(2.5,10.0)??????????????????# Random float:? 2.5 <= x < 10.0
3.1800146073117523
>>>expovariate(1/5)??????????????????# Interval between arrivals averaging 5 seconds
5.148957571865031
>>>randrange(10)???????????????????????# Integer from 0 to 9 inclusive
7
>>>randrange(0,101,2)????????????????# Even integer from 0 to 100 inclusive
26
>>>choice(['win','lose','draw'])?????# Single random element from a sequence
'draw'
>>>deck='ace two three four'.split()
>>>shuffle(deck)???????????????????????# Shuffle a list
>>>deck
['four', 'two', 'ace', 'three']
>>>sample([10,20,30,40,50], k=4)???# Four samples without replacement
[40, 10, 50, 30]
模擬:
>>># Six roulette wheel spins (weighted sampling with replacement)
>>>choices(['red','black','green'], [18,18,2], k=6)
['red', 'green', 'black', 'black', 'red', 'black']
>>># Deal 20 cards without replacement from a deck of 52 playing cards
>>># and determine the proportion of cards with a ten-value
>>># (a ten, jack, queen, or king).
>>>deck=collections.Counter(tens=16, low_cards=36)
>>>seen=sample(list(deck.elements()), k=20)
>>>seen.count('tens')/20
0.15
>>># Estimate the probability of getting 5 or more heads from 7 spins
>>># of a biased coin that settles on heads 60% of the time.
>>>trial=lambda: choices('HT', cum_weights=(0.60,1.00), k=7).count('H')>=5
>>>sum(trial()foriinrange(10000))/10000
0.4169
>>># Probability of the median of 5 samples being in middle two quartiles
>>>trial=lambda:2500<=sorted(choices(range(10000), k=5))[2]?<7500
>>>sum(trial()foriinrange(10000))/10000
0.7958
statistical bootstrapping?使用重采樣和替換來估計大小為五的樣本的均值的置信區(qū)間的示例:
#http://statistics.about.com/od/Applications/a/Example-Of-Bootstrapping.htm
fromstatisticsimportmean
fromrandomimportchoices
data=1,2,4,4,10
means=sorted(mean(choices(data, k=5))foriinrange(20))
print(f'The sample mean of {mean(data):.1f} has a 90% confidence '
?????f'interval from{means[1]:.1f}to{means[-2]:.1f}')
使用?重新采樣排列測試?來確定統(tǒng)計學(xué)顯著性或者使用?p-值?來觀察藥物與安慰劑的作用之間差異的示例:
# Example from "Statistics is Easy" by Dennis Shasha and Manda Wilson
fromstatisticsimportmean
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=10000
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}label reshufflings produced only{count}instances with a difference')
print(f'at least as extreme as the observed difference of{observed_diff:.1f}.')
print(f'The one-sided p-value of {count / n:.4f} leads us to reject the null')
print(f'hypothesis that there is no difference between the drug and the placebo.')
模擬單個服務(wù)器隊列中的到達(dá)時間和服務(wù)交付:
fromrandomimportexpovariate, gauss
fromstatisticsimportmean, median, stdev
average_arrival_interval=5.6
average_service_time=5.0
stdev_service_time=0.5
num_waiting=0
arrivals=[]
starts=[]
arrival=service_end=0.0
foriinrange(20000):
???ifarrival<=service_end:
??????? num_waiting+=1
??????? arrival+=expovariate(1.0/average_arrival_interval)
??????? arrivals.append(arrival)
???else:
??????? num_waiting-=1
??????? service_start=service_endifnum_waitingelsearrival
??????? service_time=gauss(average_service_time, stdev_service_time)
??????? service_end=service_start+service_time
??????? starts.append(service_start)
waits=[start-arrivalforarrival, startinzip(arrivals, starts)]
print(f'Mean wait: {mean(waits):.1f}.? Stdev wait: {stdev(waits):.1f}.')
print(f'Median wait: {median(waits):.1f}.? Max wait: {max(waits):.1f}.')