random --- 生成偽隨機(jī)數(shù)?

源碼: Lib/random.py


該模塊實(shí)現(xiàn)了各種分布的偽隨機(jī)數(shù)生成器。

對(duì)于整數(shù),從范圍中有統(tǒng)一的選擇。 對(duì)于序列,存在隨機(jī)元素的統(tǒng)一選擇、用于生成列表的隨機(jī)排列的函數(shù)、以及用于隨機(jī)抽樣而無(wú)需替換的函數(shù)。

在實(shí)數(shù)軸上,有計(jì)算均勻、正態(tài)(高斯)、對(duì)數(shù)正態(tài)、負(fù)指數(shù)、伽馬和貝塔分布的函數(shù)。 為了生成角度分布,可以使用 von Mises 分布。

幾乎所有模塊函數(shù)都依賴于基本函數(shù) random() ,它在半開(kāi)放區(qū)間 [0.0,1.0) 內(nèi)均勻生成隨機(jī)浮點(diǎn)數(shù)。 Python 使用 Mersenne Twister 作為核心生成器。 它產(chǎn)生 53 位精度浮點(diǎn)數(shù),周期為 2**19937-1 ,其在 C 中的底層實(shí)現(xiàn)既快又線程安全。 Mersenne Twister 是現(xiàn)存最廣泛測(cè)試的隨機(jī)數(shù)發(fā)生器之一。 但是,因?yàn)橥耆_定性,它不適用于所有目的,并且完全不適合加密目的。

這個(gè)模塊提供的函數(shù)實(shí)際上是 random.Random 類的隱藏實(shí)例的綁定方法。 你可以實(shí)例化自己的 Random 類實(shí)例以獲取不共享狀態(tài)的生成器。

如果你想使用自己設(shè)計(jì)的不同基礎(chǔ)生成器,類 Random?也可以作為子類:在這種情況下,重載 random()seed() 、 getstate() 以及 setstate()?方法??蛇x地,新生成器可以提供 getrandbits() 方法——這允許 randrange() 在任意大的范圍內(nèi)產(chǎn)生選擇。

random 模塊還提供 SystemRandom 類,它使用系統(tǒng)函數(shù) os.urandom() 從操作系統(tǒng)提供的源生成隨機(jī)數(shù)。

警告

不應(yīng)將此模塊的偽隨機(jī)生成器用于安全目的。 有關(guān)安全性或加密用途,請(qǐng)參閱 secrets 模塊。

參見(jiàn)

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 用于兼容的替代隨機(jī)數(shù)發(fā)生器,具有長(zhǎng)周期和相對(duì)簡(jiǎn)單的更新操作。

簿記功能?

random.seed(a=None, version=2)?

初始化隨機(jī)數(shù)生成器。

如果 a 被省略或?yàn)?None ,則使用當(dāng)前系統(tǒng)時(shí)間。 如果操作系統(tǒng)提供隨機(jī)源,則使用它們而不是系統(tǒng)時(shí)間(有關(guān)可用性的詳細(xì)信息,請(qǐng)參閱 os.urandom() 函數(shù))。

如果 a 是 int 類型,則直接使用。

對(duì)于版本2(默認(rèn)的),str 、 bytesbytearray 對(duì)象轉(zhuǎn)換為 int 并使用它的所有位。

對(duì)于版本1(用于從舊版本的Python再現(xiàn)隨機(jī)序列),用于 strbytes 的算法生成更窄的種子范圍。

在 3.2 版更改: 已移至版本2方案,該方案使用字符串種子中的所有位。

random.getstate()?

返回捕獲生成器當(dāng)前內(nèi)部狀態(tài)的對(duì)象。 這個(gè)對(duì)象可以傳遞給 setstate() 來(lái)恢復(fù)狀態(tài)。

random.setstate(state)?

state 應(yīng)該是從之前調(diào)用 getstate() 獲得的,并且 setstate() 將生成器的內(nèi)部狀態(tài)恢復(fù)到 getstate() 被調(diào)用時(shí)的狀態(tài)。

random.getrandbits(k)?

返回帶有 k 位隨機(jī)的Python整數(shù)。 此方法隨 MersenneTwister 生成器一起提供,其他一些生成器也可以將其作為API的可選部分提供。 如果可用,getrandbits() 啟用 randrange() 來(lái)處理任意大范圍。

整數(shù)用函數(shù)?

random.randrange(stop)?
random.randrange(start, stop[, step])

range(start, stop, step) 返回一個(gè)隨機(jī)選擇的元素。 這相當(dāng)于 choice(range(start, stop, step)) ,但實(shí)際上并沒(méi)有構(gòu)建一個(gè) range 對(duì)象。

位置參數(shù)模式匹配 range() 。不應(yīng)使用關(guān)鍵字參數(shù),因?yàn)樵摵瘮?shù)可能以意外的方式使用它們。

在 3.2 版更改: randrange() 在生成均勻分布的值方面更為復(fù)雜。 以前它使用了像``int(random()*n)``這樣的形式,它可以產(chǎn)生稍微不均勻的分布。

random.randint(a, b)?

返回隨機(jī)整數(shù) N 滿足 a <= N <= b。相當(dāng)于 randrange(a, b+1)。

序列用函數(shù)?

random.choice(seq)?

從非空序列 seq 返回一個(gè)隨機(jī)元素。 如果 seq 為空,則引發(fā) IndexError

random.choices(population, weights=None, *, cum_weights=None, k=1)?

從*population*中選擇替換,返回大小為 k 的元素列表。 如果 population 為空,則引發(fā) IndexError。

如果指定了 weight 序列,則根據(jù)相對(duì)權(quán)重進(jìn)行選擇。 或者,如果給出 cum_weights 序列,則根據(jù)累積權(quán)重(可能使用 itertools.accumulate() 計(jì)算)進(jìn)行選擇。 例如,相對(duì)權(quán)重``[10, 5, 30, 5]``相當(dāng)于累積權(quán)重``[10, 15, 45, 50]``。 在內(nèi)部,相對(duì)權(quán)重在進(jìn)行選擇之前會(huì)轉(zhuǎn)換為累積權(quán)重,因此提供累積權(quán)重可以節(jié)省工作量。

如果既未指定 weight 也未指定 cum_weights ,則以相等的概率進(jìn)行選擇。 如果提供了權(quán)重序列,則它必須與 population 序列的長(zhǎng)度相同。 一個(gè) TypeError 指定了 weights 和*cum_weights*。

weightscum_weights 可以使用任何與 random() 返回的 float 值互操作的數(shù)值類型(包括整數(shù),浮點(diǎn)數(shù)和分?jǐn)?shù)但不包括十進(jìn)制小數(shù))。

對(duì)于給定的種子,具有相等加權(quán)的 choices() 函數(shù)通常產(chǎn)生與重復(fù)調(diào)用 choice() 不同的序列。 choices() 使用的算法使用浮點(diǎn)運(yùn)算來(lái)實(shí)現(xiàn)內(nèi)部一致性和速度。 choice() 使用的算法默認(rèn)為重復(fù)選擇的整數(shù)運(yùn)算,以避免因舍入誤差引起的小偏差。

3.6 新版功能.

random.shuffle(x[, random])?

將序列 x 隨機(jī)打亂位置。

可選參數(shù) random 是一個(gè)0參數(shù)函數(shù),在 [0.0, 1.0) 中返回隨機(jī)浮點(diǎn)數(shù);默認(rèn)情況下,這是函數(shù) random()

要改變一個(gè)不可變的序列并返回一個(gè)新的打亂列表,請(qǐng)使用``sample(x, k=len(x))``。

請(qǐng)注意,即使對(duì)于小的 len(x)x 的排列總數(shù)也可以快速增長(zhǎng),大于大多數(shù)隨機(jī)數(shù)生成器的周期。 這意味著長(zhǎng)序列的大多數(shù)排列永遠(yuǎn)不會(huì)產(chǎn)生。 例如,長(zhǎng)度為2080的序列是可以在 Mersenne Twister 隨機(jī)數(shù)生成器的周期內(nèi)擬合的最大序列。

random.sample(population, k)?

返回從總體序列或集合中選擇的唯一元素的 k 長(zhǎng)度列表。 用于無(wú)重復(fù)的隨機(jī)抽樣。

返回包含來(lái)自總體的元素的新列表,同時(shí)保持原始總體不變。 結(jié)果列表按選擇順序排列,因此所有子切片也將是有效的隨機(jī)樣本。 這允許抽獎(jiǎng)獲獎(jiǎng)?wù)撸颖荆┍粍澐譃榇螵?jiǎng)和第二名獲勝者(子切片)。

總體成員不必是 hashable 或 unique 。 如果總體包含重復(fù),則每次出現(xiàn)都是樣本中可能的選擇。

要從一系列整數(shù)中選擇樣本,請(qǐng)使用 range() 對(duì)象作為參數(shù)。 對(duì)于從大量人群中采樣,這種方法特別快速且節(jié)省空間:sample(range(10000000), k=60)

如果樣本大小大于總體大小,則引發(fā) ValueError

實(shí)值分布?

以下函數(shù)生成特定的實(shí)值分布。如常用數(shù)學(xué)實(shí)踐中所使用的那樣, 函數(shù)參數(shù)以分布方程中的相應(yīng)變量命名;大多數(shù)這些方程都可以在任何統(tǒng)計(jì)學(xué)教材中找到。

random.random()?

返回 [0.0, 1.0) 范圍內(nèi)的下一個(gè)隨機(jī)浮點(diǎn)數(shù)。

random.uniform(a, b)?

返回一個(gè)隨機(jī)浮點(diǎn)數(shù) N ,當(dāng) a <= b 時(shí) a <= N <= b ,當(dāng) b < a 時(shí) b <= N <= a 。

取決于等式 a + (b-a) * random() 中的浮點(diǎn)舍入,終點(diǎn) b 可以包括或不包括在該范圍內(nèi)。

random.triangular(low, high, mode)?

返回一個(gè)隨機(jī)浮點(diǎn)數(shù) N ,使得 low <= N <= high 并在這些邊界之間使用指定的 mode 。 lowhigh 邊界默認(rèn)為零和一。 mode 參數(shù)默認(rèn)為邊界之間的中點(diǎn),給出對(duì)稱分布。

random.betavariate(alpha, beta)?

Beta 分布。 參數(shù)的條件是 alpha > 0beta > 0。 返回值的范圍介于 0 和 1 之間。

random.expovariate(lambd)?

指數(shù)分布。 lambd 是 1.0 除以所需的平均值,它應(yīng)該是非零的。 (該參數(shù)本應(yīng)命名為 “l(fā)ambda” ,但這是 Python 中的保留字。)如果 lambd 為正,則返回值的范圍為 0 到正無(wú)窮大;如果 lambd 為負(fù),則返回值從負(fù)無(wú)窮大到 0。

random.gammavariate(alpha, beta)?

Gamma 分布。 ( 不是 gamma 函數(shù)! ) 參數(shù)的條件是 alpha > 0beta > 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)?

對(duì)數(shù)正態(tài)分布。 如果你采用這個(gè)分布的自然對(duì)數(shù),你將得到一個(gè)正態(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)?

馮·米塞斯分布。 mu 是平均角度,以弧度表示,介于0和 2*pi 之間,kappa 是濃度參數(shù),必須大于或等于零。 如果 kappa 等于零,則該分布在 0 到 2*pi 的范圍內(nèi)減小到均勻的隨機(jī)角度。

random.paretovariate(alpha)?

帕累托分布。 alpha 是形狀參數(shù)。

random.weibullvariate(alpha, beta)?

威布爾分布。 alpha 是比例參數(shù),beta 是形狀參數(shù)。

替代生成器?

class random.Random([seed])?

該類實(shí)現(xiàn)了 random 模塊所用的默認(rèn)偽隨機(jī)數(shù)生成器。

class random.SystemRandom([seed])?

使用 os.urandom() 函數(shù)的類,用從操作系統(tǒng)提供的源生成隨機(jī)數(shù)。 這并非適用于所有系統(tǒng)。 也不依賴于軟件狀態(tài),序列不可重現(xiàn)。 因此,seed() 方法沒(méi)有效果而被忽略。 getstate()setstate() 方法如果被調(diào)用則引發(fā) NotImplementedError。

關(guān)于再現(xiàn)性的說(shuō)明?

有時(shí)能夠重現(xiàn)偽隨機(jī)數(shù)生成器給出的序列是有用的。 通過(guò)重新使用種子值,只要多個(gè)線程沒(méi)有運(yùn)行,相同的序列就可以在兩次不同運(yùn)行之間重現(xiàn)。

大多數(shù)隨機(jī)模塊的算法和種子函數(shù)都會(huì)在 Python 版本中發(fā)生變化,但保證兩個(gè)方面不會(huì)改變:

  • 如果添加了新的播種方法,則將提供向后兼容的播種機(jī)。

  • 當(dāng)兼容的播種機(jī)被賦予相同的種子時(shí),生成器的 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.
>>> def trial():
...     return choices('HT', cum_weights=(0.60, 1.00), k=7).count('H') >= 5
...
>>> sum(trial() for i in range(10000)) / 10000
0.4169

>>> # Probability of the median of 5 samples being in middle two quartiles
>>> def trial():
...     return 2500 <= sorted(choices(range(10000), k=5))[2] < 7500
...
>>> sum(trial() for i in range(10000)) / 10000
0.7958

statistical bootstrapping 使用重采樣和替換來(lái)估計(jì)大小為五的樣本的均值的置信區(qū)間的示例:

# http://statistics.about.com/od/Applications/a/Example-Of-Bootstrapping.htm
from statistics import mean
from random import choices

data = 1, 2, 4, 4, 10
means = sorted(mean(choices(data, k=5)) for i in range(20))
print(f'The sample mean of {mean(data):.1f} has a 90% confidence '
      f'interval from {means[1]:.1f} to {means[-2]:.1f}')

使用 重新采樣排列測(cè)試 來(lái)確定統(tǒng)計(jì)學(xué)顯著性或者使用 p-值 來(lái)觀察藥物與安慰劑的作用之間差異的示例:

# Example from "Statistics is Easy" by Dennis Shasha and Manda Wilson
from statistics import mean
from random import shuffle

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
for i in range(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.')

模擬單個(gè)服務(wù)器隊(duì)列中的到達(dá)時(shí)間和服務(wù)交付:

from random import expovariate, gauss
from statistics import mean, 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
for i in range(20000):
    if arrival <= service_end:
        num_waiting += 1
        arrival += expovariate(1.0 / average_arrival_interval)
        arrivals.append(arrival)
    else:
        num_waiting -= 1
        service_start = service_end if num_waiting else arrival
        service_time = gauss(average_service_time, stdev_service_time)
        service_end = service_start + service_time
        starts.append(service_start)

waits = [start - arrival for arrival, start in zip(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}.')

參見(jiàn)

Statistics for Hackers Jake Vanderplas 撰寫(xiě)的視頻教程,使用一些基本概念進(jìn)行統(tǒng)計(jì)分析,包括模擬、抽樣、改組和交叉驗(yàn)證。

Economics Simulation Peter Norvig 編寫(xiě)的市場(chǎng)模擬,顯示了該模塊提供的許多工具和分布的有效使用(高斯、均勻、樣本、beta變量、選擇、三角和隨機(jī)范圍等)。

A Concrete Introduction to Probability (using Python) Peter Norvig 撰寫(xiě)的教程,涵蓋了概率論基礎(chǔ)知識(shí),如何編寫(xiě)模擬,以及如何使用 Python 進(jìn)行數(shù)據(jù)分析。