該模塊實(shí)現(xiàn)了各種分布的偽隨機(jī)數(shù)生成器。
對(duì)于整數(shù),從范圍中有統(tǒng)一的選擇。 對(duì)于序列,存在隨機(jī)元素的統(tǒng)一選擇、用于生成列表的隨機(jī)排列的函數(shù)、以及用于隨機(jī)抽樣而無需替換的函數(shù)。
在實(shí)數(shù)軸上,有計(jì)算均勻、正態(tài)(高斯)、對(duì)數(shù)正態(tài)、負(fù)指數(shù)、伽馬和貝塔分布的函數(shù)。 為了生成角度分布,可以使用 von Mises 分布。
幾乎所有的模塊函數(shù)都依賴于基本函數(shù)random(),該函數(shù)在半開范圍0.0<=X<1.0內(nèi)均勻生成隨機(jī)浮點(diǎn)。Python使用Mersenne Twister作為核心生成器。它產(chǎn)生53位精度浮點(diǎn),周期為2**19937-1。C語言中的底層實(shí)現(xiàn)既快速又線程安全。Mersenne Twister是目前測(cè)試最廣泛的隨機(jī)數(shù)生成器之一。然而,由于它是完全確定性的,它并不適用于所有目的,并且完全不適用于加密目的。
這個(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 模塊。
簿記功能
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 、 bytes 或 bytearray 對(duì)象轉(zhuǎn)換為 int 并使用它的所有位。
對(duì)于版本1(用于從舊版本的Python再現(xiàn)隨機(jī)序列),用于 str 和 bytes 的算法生成更窄的種子范圍。
在 3.2 版更改: 已移至版本2方案,該方案使用字符串種子中的所有位。
在 3.11 版更改: The seed must be one of the following types: NoneType, int, float, str, bytes, or bytearray.
random.getstate()
返回捕獲生成器當(dāng)前內(nèi)部狀態(tài)的對(duì)象。 這個(gè)對(duì)象可以傳遞給 setstate() 來恢復(fù)狀態(tài)。
random.setstate(state)
state 應(yīng)該是從之前調(diào)用 getstate() 獲得的,并且 setstate() 將生成器的內(nèi)部狀態(tài)恢復(fù)到 getstate() 被調(diào)用時(shí)的狀態(tài)。
用于字節(jié)數(shù)據(jù)的函數(shù)
random.randbytes(n)
生成 n 個(gè)隨機(jī)字節(jié)。
此方法不可用于生成安全憑據(jù)。 那應(yīng)當(dāng)使用 secrets.token_bytes()。
3.9 新版功能.
整數(shù)用函數(shù)
random.randrange(stop)
random.randrange(start, stop[, step])
從 range(start, stop, step) 返回一個(gè)隨機(jī)選擇的元素。 這相當(dāng)于 choice(range(start, stop, step)) ,但實(shí)際上并沒有構(gòu)建一個(gè) range 對(duì)象。
位置參數(shù)模式匹配 range() 。不應(yīng)使用關(guān)鍵字參數(shù),因?yàn)樵摵瘮?shù)可能以意外的方式使用它們。
在 3.2 版更改: randrange() 在生成均勻分布的值方面更為復(fù)雜。 以前它使用了像int(random()*n)
這樣的形式,它可以產(chǎn)生稍微不均勻的分布。
3.10 版后已移除: 非整數(shù)類型到相等整數(shù)的自動(dòng)轉(zhuǎn)換已被棄用。 目前 randrange(10.0) 會(huì)無損地轉(zhuǎn)換為 randrange(10)。 在未來,這將引發(fā) TypeError。
3.10 版后已移除: 針對(duì)非整數(shù)值例如 randrange(10.5) 或 randrange(‘10’) 引發(fā)的異常將從 ValueError 修改為 TypeError。
random.randint(a, b)
返回隨機(jī)整數(shù) N 滿足 a <= N <= b。相當(dāng)于 randrange(a, b+1)。
random.getrandbits(k)
返回具有 k 個(gè)隨機(jī)比特位的非負(fù) Python 整數(shù)。 此方法隨 MersenneTwister 生成器一起提供,其他一些生成器也可能將其作為 API 的可選部分提供。 在可能的情況下,getrandbits() 會(huì)啟用 randrange() 來處理任意大的區(qū)間。
在 3.9 版更改: 此方法現(xiàn)在接受零作為 k 的值。
序列用函數(shù)
random.choice(seq)
從非空序列 seq 返回一個(gè)隨機(jī)元素。 如果 seq 為空,則引發(fā) IndexError。
random.choices(population, weights=None, *, cum_weights=None, k=1)
從 population 中有重復(fù)地隨機(jī)選取元素,返回大小為 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 。
weights 或 cum_weights 可使用 random() 所返回的能與 float 值進(jìn)行相互運(yùn)算的任何數(shù)字類型(包括整數(shù)、浮點(diǎn)數(shù)、分?jǐn)?shù)但不包括 decimal)。 權(quán)重值應(yīng)當(dāng)非負(fù)且為有限的數(shù)值。 如果所有的權(quán)重值均為零則會(huì)引發(fā) ValueError。
對(duì)于給定的種子,具有相等加權(quán)的 choices() 函數(shù)通常產(chǎn)生與重復(fù)調(diào)用 choice() 不同的序列。 choices() 使用的算法使用浮點(diǎn)運(yùn)算來實(shí)現(xiàn)內(nèi)部一致性和速度。 choice() 使用的算法默認(rèn)為重復(fù)選擇的整數(shù)運(yùn)算,以避免因舍入誤差引起的小偏差。
3.6 新版功能.
在 3.9 版更改: 如果所有權(quán)重均為負(fù)值則將引發(fā) ValueError。
random.shuffle(x)
就地將序列 x 隨機(jī)打亂位置。
要改變一個(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)擬合的最大序列。
從版本 3.9 起棄用,在版本 3.11 中移除。: 可選形參 random。
random.sample(population, k, *, counts=None)
Return a k length list of unique elements chosen from the population sequence. Used for random sampling without replacement.
返回包含來自總體的元素的新列表,同時(shí)保持原始總體不變。 結(jié)果列表按選擇順序排列,因此所有子切片也將是有效的隨機(jī)樣本。 這允許抽獎(jiǎng)獲獎(jiǎng)?wù)撸颖荆┍粍澐譃榇螵?jiǎng)和第二名獲勝者(子切片)。
總體成員不必是 hashable 或 unique 。 如果總體包含重復(fù),則每次出現(xiàn)都是樣本中可能的選擇。
重復(fù)的元素可以一個(gè)個(gè)地直接列出,或使用可選的僅限關(guān)鍵字形參 counts 來指定。 例如,sample([‘red’, ‘blue’], counts=[4, 2], k=5) 等價(jià)于 sample([‘red’, ‘red’, ‘red’, ‘red’, ‘blue’, ‘blue’], k=5)。
要從一系列整數(shù)中選擇樣本,請(qǐng)使用 range() 對(duì)象作為參數(shù)。 對(duì)于從大量人群中采樣,這種方法特別快速且節(jié)省空間:sample(range(10000000), k=60) 。
如果樣本大小大于總體大小,則引發(fā) ValueError 。
在 3.9 版更改: 增加了 counts 形參。
在 3.11 版更改: The population must be a sequence. Automatic conversion of sets to lists is no longer supported.
實(shí)值分布
以下函數(shù)生成特定的實(shí)值分布。如常用數(shù)學(xué)實(shí)踐中所使用的那樣,函數(shù)形參以分布方程中的相應(yīng)變量命名,大多數(shù)這些方程都可以在任何統(tǒng)計(jì)學(xué)教材中找到。
random.random()
Return the next random floating point number in the range 0.0 <= X < 1.0
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 。 low 和 high 邊界默認(rèn)為零和一。 mode 參數(shù)默認(rèn)為邊界之間的中點(diǎn),給出對(duì)稱分布。
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=0.0, sigma=1.0)
正態(tài)分布,也稱高斯分布。 mu 為平均值,而 sigma 為標(biāo)準(zhǔn)差。 此函數(shù)要稍快于下面所定義的 normalvariate() 函數(shù)。
多線程注意事項(xiàng):當(dāng)兩個(gè)線程同時(shí)調(diào)用此方法時(shí),它們有可能將獲得相同的返回值。 這可以通過三種辦法來避免。 1) 讓每個(gè)線程使用不同的隨機(jī)數(shù)生成器實(shí)例。 2) 在所有調(diào)用外面加鎖。 3) 改用速度較慢但是線程安全的 normalvariate() 函數(shù)。
在 3.11 版更改: mu and sigma now have default arguments.
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=0.0, sigma=1.0)
正態(tài)分布。 mu 是平均值,sigma 是標(biāo)準(zhǔn)差。
在 3.11 版更改: mu and sigma now have default arguments.
random.vonmisesvariate(mu, kappa)
馮·米塞斯分布。 mu 是平均角度,以弧度表示,介于0和 2pi 之間,kappa 是濃度參數(shù),必須大于或等于零。 如果 kappa 等于零,則該分布在 0 到 2pi 的范圍內(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ù)生成器。
3.9 版后已移除: 在將來,seed 必須是下列類型之一: NoneType, int, float, str, bytes 或 bytearray。
class random.SystemRandom([seed])
使用 os.urandom() 函數(shù)的類,用從操作系統(tǒng)提供的源生成隨機(jī)數(shù)。 這并非適用于所有系統(tǒng)。 也不依賴于軟件狀態(tài),序列不可重現(xiàn)。 因此,seed() 方法沒有效果而被忽略。 getstate() 和 setstate() 方法如果被調(diào)用則引發(fā) NotImplementedError。
關(guān)于再現(xiàn)性的說明
有時(shí)能夠重現(xiàn)偽隨機(jī)數(shù)生成器給出的序列是很有用處的。 通過重用一個(gè)種子值,只要沒有運(yùn)行多線程,相同的序列就應(yīng)當(dāng)可在多次運(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: ten, jack, queen, or king.
dealt = sample(['tens', 'low cards'], counts=[16, 36], k=20)
dealt.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(10_000)) / 10_000
0.4169
# Probability of the median of 5 samples being in middle two quartiles
def trial():
return 2_500 <= sorted(choices(range(10_000), k=5))[2] < 7_500
sum(trial() for i in range(10_000)) / 10_000
0.7958
statistical bootstrapping 的示例,使用重新采樣和替換來估計(jì)一個(gè)樣本的均值的置信區(qū)間:
# https://www.thoughtco.com/example-of-bootstrapping-3126155
from statistics import fmean as mean
from random import choices
data = [41, 50, 29, 37, 81, 30, 73, 63, 20, 35, 68, 22, 60, 31, 95]
means = sorted(mean(choices(data, k=len(data))) for i in range(100))
print(f'The sample mean of {mean(data):.1f} has a 90% confidence '
f'interval from {means[5]:.1f} to {means[94]:.1f}')
使用 重新采樣排列測(cè)試 來確定統(tǒng)計(jì)學(xué)顯著性或者使用 p-值 來觀察藥物與安慰劑的作用之間差異的示例:
# Example from "Statistics is Easy" by Dennis Shasha and Manda Wilson
from statistics import fmean as 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 = 10_000
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.')
多服務(wù)器隊(duì)列的到達(dá)時(shí)間和服務(wù)交付模擬:
from heapq import heapify, heapreplace
from random import expovariate, gauss
from statistics import mean, 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 # time when each server becomes available
heapify(servers)
for i in range(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'Mean wait: {mean(waits):.1f} Max wait: {max(waits):.1f}')
print('Quartiles:', [round(q, 1) for q in quantiles(waits)])
參見 Statistics for Hackers Jake Vanderplas 撰寫的視頻教程,使用一些基本概念進(jìn)行統(tǒng)計(jì)分析,包括模擬、抽樣、洗牌和交叉驗(yàn)證。
例程
These recipes show how to efficiently make random selections from the combinatoric iterators in the itertools module:
def random_product(*args, repeat=1):
"Random selection from itertools.product(*args, **kwds)"
pools = [tuple(pool) for pool in args] * repeat
return tuple(map(random.choice, pools))
def random_permutation(iterable, r=None):
"Random selection from itertools.permutations(iterable, r)"
pool = tuple(iterable)
r = len(pool) if r is None else r
return tuple(random.sample(pool, r))
def random_combination(iterable, r):
"Random selection from itertools.combinations(iterable, r)"
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.sample(range(n), r))
return tuple(pool[i] for i in indices)
def random_combination_with_replacement(iterable, r):
"Random selection from itertools.combinations_with_replacement(iterable, r)"
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.choices(range(n), k=r))
return tuple(pool[i] for i in indices)
默認(rèn)的 random() 返回在 0.0 ≤ x < 1.0 范圍內(nèi) 2??3 的倍數(shù)。 所有這些數(shù)值間隔相等并能精確表示為 Python 浮點(diǎn)數(shù)。 但是在此間隔上有許多其他可表示浮點(diǎn)數(shù)是不可能的選擇。 例如,0.05954861408025609 就不是 2??3 的整數(shù)倍。
以下規(guī)范程序采取了一種不同的方式。 在間隔上的所有浮點(diǎn)數(shù)都是可能的選擇。 它們的尾數(shù)取值來自 2?2 ≤ 尾數(shù) < 2?3 范圍內(nèi)整數(shù)的均勻分布。 指數(shù)取值則來自幾何分布,其中小于 -53 的指數(shù)的出現(xiàn)頻率為下一個(gè)較大指數(shù)的一半。
from random import Random
from math import ldexp
class FullRandom(Random):
def random(self):
mantissa = 0x10_0000_0000_0000 | self.getrandbits(52)
exponent = -53
x = 0
while not x:
x = self.getrandbits(32)
exponent += x.bit_length() - 32
return ldexp(mantissa, exponent)
該類中所有的 實(shí)值分布 都將使用新的方法:
>>>
fr = FullRandom()
fr.random()
0.05954861408025609
fr.expovariate(0.25)
8.87925541791544
該規(guī)范程序在概念上等效于在 0.0 ≤ x < 1.0 范圍內(nèi)對(duì)所有 2?1??? 的倍數(shù)進(jìn)行選擇的算法。 所有這樣的數(shù)字間隔都相等,但大多必須向下舍入為最接近的 Python 浮點(diǎn)數(shù)表示形式。 (2?1??? 這個(gè)數(shù)值是等于 math.ulp(0.0) 的未經(jīng)正規(guī)化的最小正浮點(diǎn)數(shù)。)文章來源:http://www.zghlxwxcb.cn/news/detail-697786.html
參見 生成偽隨機(jī)浮點(diǎn)數(shù)值 為 Allen B. Downey 所撰寫的描述如何生成相比通過 random() 正常生成的數(shù)值更細(xì)粒度浮點(diǎn)數(shù)的論文。文章來源地址http://www.zghlxwxcb.cn/news/detail-697786.html
到了這里,關(guān)于python:random --- 生成偽隨機(jī)數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!