random
— Generate pseudo-random numbers¶
Вихідний код: Lib/random.py
Цей модуль реалізує генератори псевдовипадкових чисел для різних розподілів.
Для цілих чисел існує рівномірний вибір із діапазону. Для послідовностей існує рівномірний вибір випадкового елемента, функція для створення випадкової перестановки списку на місці та функція для випадкової вибірки без заміни.
На реальній лінії існують функції для обчислення рівномірного, нормального (гауссового), логарифмічного нормального, від’ємного експоненціального, гамма- та бета-розподілу. Для генерації розподілу кутів доступний розподіл фон Мізеса.
Almost all module functions depend on the basic function random()
, which
generates a random float uniformly in the half-open range 0.0 <= X < 1.0
.
Python uses the Mersenne Twister as the core generator. It produces 53-bit precision
floats and has a period of 2**19937-1. The underlying implementation in C is
both fast and threadsafe. The Mersenne Twister is one of the most extensively
tested random number generators in existence. However, being completely
deterministic, it is not suitable for all purposes, and is completely unsuitable
for cryptographic purposes.
Функції, які надає цей модуль, насправді є зв’язаними методами прихованого екземпляра класу random.Random
. Ви можете створити власні екземпляри Random
, щоб отримати генератори, які не мають спільного стану.
Class Random
can also be subclassed if you want to use a different
basic generator of your own devising: see the documentation on that class for
more details.
Модуль random
також надає клас SystemRandom
, який використовує системну функцію os.urandom()
для генерування випадкових чисел із джерел, наданих операційною системою.
Попередження
Псевдовипадкові генератори цього модуля не слід використовувати з метою безпеки. Щоб отримати відомості про безпеку чи криптографію, перегляньте модуль secrets
.
Дивись також
M. Matsumoto and T. Nishimura, «Mersenne Twister: 623-dimensionally equidistributed uniform pseudorandom number generator», ACM Transactions on Modeling and Computer Simulation Vol. 8, № 1, січень 3-30 1998.
Complementary-Multiply-with-Carry recipe for a compatible alternative random number generator with a long period and comparatively simple update operations.
Бухгалтерські функції¶
- random.seed(a=None, version=2)¶
Ініціалізуйте генератор випадкових чисел.
Якщо a пропущено або
None
, використовується поточний системний час. Якщо джерела випадковості надаються операційною системою, вони використовуються замість системного часу (дивіться функціюos.urandom()
, щоб дізнатися більше про доступність).Якщо a є int, воно використовується безпосередньо.
У версії 2 (за замовчуванням) об’єкт
str
,bytes
абоbytearray
перетворюється наint
і використовуються всі його біти.У версії 1 (надається для відтворення випадкових послідовностей зі старих версій Python) алгоритм для
str
іbytes
генерує вужчий діапазон початкових значень.Змінено в версії 3.2: Перенесено на схему версії 2, яка використовує всі біти початкового рядка.
- random.getstate()¶
Повертає об’єкт, що фіксує поточний внутрішній стан генератора. Цей об’єкт можна передати
setstate()
для відновлення стану.
- random.setstate(state)¶
state мав бути отриманий з попереднього виклику
getstate()
, аsetstate()
відновлює внутрішній стан генератора до того, яким він був на момент викликуgetstate()
.
Функції для байтів¶
- random.randbytes(n)¶
Згенерувати n випадкових байтів.
Цей метод не слід використовувати для генерації маркерів безпеки. Натомість використовуйте
secrets.token_bytes()
.Нове в версії 3.9.
Функції для цілих чисел¶
- random.randrange(stop)¶
- random.randrange(start, stop[, step])
Return a randomly selected element from
range(start, stop, step)
. This is equivalent tochoice(range(start, stop, step))
, but doesn’t actually build a range object.The positional argument pattern matches that of
range()
. Keyword arguments should not be used because the function may use them in unexpected ways.Змінено в версії 3.2:
randrange()
більш складний у створенні рівномірно розподілених значень. Раніше він використовував такий стиль, якint(random()*n)
, який міг створити дещо нерівномірний розподіл.Застаріло починаючи з версії 3.10: The automatic conversion of non-integer types to equivalent integers is deprecated. Currently
randrange(10.0)
is losslessly converted torandrange(10)
. In the future, this will raise aTypeError
.Застаріло починаючи з версії 3.10: The exception raised for non-integer values such as
randrange(10.5)
orrandrange('10')
will be changed fromValueError
toTypeError
.
- random.randint(a, b)¶
Повертає випадкове ціле число N таке, що
a <= N <= b
. Псевдонім дляrandrange(a, b+1)
.
- random.getrandbits(k)¶
Returns a non-negative Python integer with k random bits. This method is supplied with the MersenneTwister generator and some other generators may also provide it as an optional part of the API. When available,
getrandbits()
enablesrandrange()
to handle arbitrarily large ranges.Змінено в версії 3.9: Цей метод тепер приймає нуль для k.
Функції для послідовностей¶
- random.choice(seq)¶
Повертає випадковий елемент із непорожньої послідовності seq. Якщо seq порожній, викликає
IndexError
.
- random.choices(population, weights=None, *, cum_weights=None, k=1)¶
Повертає список елементів розміром k, вибраних із популяції із заміною. Якщо популяція порожня, викликає
IndexError
.Якщо вказано послідовність ваг, вибір робиться відповідно до відносних ваг. Крім того, якщо вказано послідовність cum_weights, вибір робиться відповідно до кумулятивних ваг (можливо, обчислених за допомогою
itertools.accumulate()
). Наприклад, відносні ваги[10, 5, 30, 5]
еквівалентні кумулятивним вагам[10, 15, 45, 50]
. Внутрішньо відносні ваги перетворюються на кумулятивні ваги перед вибором, тому надання кумулятивних ваг економить роботу.Якщо ані weights, ані cum_weights не вказано, вибір робиться з рівною ймовірністю. Якщо надається послідовність ваг, вона має бути такої ж довжини, що й послідовність населеності. Це
TypeError
, якщо вказати weights і cum_weights.Weights або cum_weights можуть використовувати будь-який числовий тип, який взаємодіє зі значеннями
float
, які повертаєrandom()
(це включає цілі числа, числа з плаваючою точкою та дроби, але виключає десяткові). Ваги вважаються невід’ємними та кінцевими. ПомилкаValueError
виникає, якщо всі ваги дорівнюють нулю.For a given seed, the
choices()
function with equal weighting typically produces a different sequence than repeated calls tochoice()
. The algorithm used bychoices()
uses floating point arithmetic for internal consistency and speed. The algorithm used bychoice()
defaults to integer arithmetic with repeated selections to avoid small biases from round-off error.Нове в версії 3.6.
Змінено в версії 3.9: Викликає
ValueError
, якщо всі ваги дорівнюють нулю.
- random.shuffle(x)¶
Перемішайте послідовність x на місці.
Щоб перетасувати незмінну послідовність і повернути новий перетасований список, замість цього використовуйте
sample(x, k=len(x))
.Зауважте, що навіть для невеликого
len(x)
загальна кількість перестановок x може швидко зрости більше, ніж період більшості генераторів випадкових чисел. Це означає, що більшість перестановок довгої послідовності ніколи не можуть бути згенеровані. Наприклад, послідовність довжиною 2080 є найбільшою, яка може поміститися в період генератора випадкових чисел Мерсенна Твістера.Змінено в версії 3.11: Removed the optional parameter 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.
Повертає новий список, що містить елементи з сукупності, залишаючи вихідну сукупність без змін. Отриманий список складається в порядку відбору, тому всі підзрізи також будуть дійсними випадковими вибірками. Це дозволяє розділити переможців розіграшу (зразок) на головний приз і переможців, які посідають друге місце (підрозділи).
Члени сукупності не повинні бути hashable або унікальними. Якщо популяція містить повтори, то кожен випадок є можливим вибором у вибірці.
Повторювані елементи можна вказувати по одному або за допомогою необов’язкового параметра counts, що містить лише ключове слово. Наприклад,
sample(['red', 'blue'], counts=[4, 2], k=5)
еквівалентноsample(['red', 'red', 'red' , 'червоний', 'синій', 'синій'], k=5)
.Щоб вибрати вибірку з діапазону цілих чисел, використовуйте об’єкт
range()
як аргумент. Це особливо швидко та ефективно для вибірки з великої сукупності:sample(range(10000000), k=60)
.Якщо розмір вибірки більший за розмір сукупності, виникає помилка
ValueError
.Змінено в версії 3.9: Додано параметр counts.
Змінено в версії 3.11: The population must be a sequence. Automatic conversion of sets to lists is no longer supported.
Дійсні розподіли¶
Наступні функції генерують конкретні дійсні розподіли. Параметри функції називаються за відповідними змінними в рівнянні розподілу, як це використовується в звичайній математичній практиці; більшість із цих рівнянь можна знайти в будь-якому статистичному тексті.
- random.random()¶
Return the next random floating point number in the range
0.0 <= X < 1.0
- random.uniform(a, b)¶
Return a random floating point number N such that
a <= N <= b
fora <= b
andb <= N <= a
forb < a
.The end-point value
b
may or may not be included in the range depending on floating-point rounding in the expressiona + (b-a) * random()
.
- random.triangular(low, high, mode)¶
Return a random floating point number N such that
low <= N <= high
and with the specified mode between those bounds. The low and high bounds default to zero and one. The mode argument defaults to the midpoint between the bounds, giving a symmetric distribution.
- random.betavariate(alpha, beta)¶
Бета-розповсюдження. Умови параметрів:
альфа > 0
ібета > 0
. Діапазон повернених значень від 0 до 1.
- random.expovariate(lambd)¶
Експоненціальний розподіл. lambd дорівнює 1,0, поділеному на бажане середнє. Воно повинно бути відмінним від нуля. (Параметр мав би назву «лямбда», але це зарезервоване слово в Python.) Повернені значення варіюються від 0 до нескінченності, якщо lambd додатне, і від нескінченності до 0, якщо lambd є від’ємним.
- random.gammavariate(alpha, beta)¶
Gamma distribution. (Not the gamma function!) The shape and scale parameters, alpha and beta, must have positive values. (Calling conventions vary and some sources define „beta“ as the inverse of the scale).
Функція розподілу ймовірностей:
x ** (alpha - 1) * math.exp(-x / beta) pdf(x) = -------------------------------------- math.gamma(alpha) * beta ** alpha
- random.gauss(mu=0.0, sigma=1.0)¶
Normal distribution, also called the Gaussian distribution. mu is the mean, and sigma is the standard deviation. This is slightly faster than the
normalvariate()
function defined below.Примітка щодо багатопоточності: коли два потоки викликають цю функцію одночасно, можливо, вони отримають однакове повернуте значення. Цього можна уникнути трьома способами. 1) Нехай кожен потік використовує окремий екземпляр генератора випадкових чисел. 2) Заблокуйте всі дзвінки. 3) Натомість використовуйте повільнішу, але потокобезпечну функцію
normalvariate()
.Змінено в версії 3.11: mu and sigma now have default arguments.
- random.lognormvariate(mu, sigma)¶
Лог нормального розподілу. Якщо взяти натуральний логарифм цього розподілу, ви отримаєте нормальний розподіл із середнім mu і стандартним відхиленням sigma. mu може мати будь-яке значення, а sigma має бути більше нуля.
- random.normalvariate(mu=0.0, sigma=1.0)¶
Нормальний розподіл. mu — середнє, а sigma — стандартне відхилення.
Змінено в версії 3.11: mu and sigma now have default arguments.
- random.vonmisesvariate(mu, kappa)¶
mu — середній кут, виражений у радіанах між 0 і 2*pi, а kappa — параметр концентрації, який має бути більшим або дорівнювати нулю. Якщо kappa дорівнює нулю, цей розподіл зменшується до рівномірного випадкового кута в діапазоні від 0 до 2*pi.
- random.paretovariate(alpha)¶
Розподіл Парето. альфа — це параметр форми.
- random.weibullvariate(alpha, beta)¶
Розподіл Вейбулла. альфа — параметр масштабу, а бета — параметр форми.
Альтернативний генератор¶
- class random.Random([seed])¶
Клас, який реалізує генератор псевдовипадкових чисел за замовчуванням, який використовується модулем
random
.Змінено в версії 3.11: Formerly the seed could be any hashable object. Now it is limited to:
None
,int
,float
,str
,bytes
, orbytearray
.Subclasses of
Random
should override the following methods if they wish to make use of a different basic generator:- seed(a=None, version=2)¶
Override this method in subclasses to customise the
seed()
behaviour ofRandom
instances.
- getstate()¶
Override this method in subclasses to customise the
getstate()
behaviour ofRandom
instances.
- setstate(state)¶
Override this method in subclasses to customise the
setstate()
behaviour ofRandom
instances.
- random()¶
Override this method in subclasses to customise the
random()
behaviour ofRandom
instances.
Optionally, a custom generator subclass can also supply the following method:
- getrandbits(k)¶
Override this method in subclasses to customise the
getrandbits()
behaviour ofRandom
instances.
- class random.SystemRandom([seed])¶
Клас, який використовує функцію
os.urandom()
для генерації випадкових чисел із джерел, наданих операційною системою. Доступно не на всіх системах. Не залежить від стану програмного забезпечення, і послідовності не відтворюються. Відповідно, методseed()
не має ефекту та ігнорується. Методиgetstate()
іsetstate()
під час виклику викликаютьNotImplementedError
.
Примітки щодо відтворюваності¶
Sometimes it is useful to be able to reproduce the sequences given by a pseudo-random number generator. By re-using a seed value, the same sequence should be reproducible from run to run as long as multiple threads are not running.
Більшість алгоритмів і функцій заповнення випадкового модуля можуть змінюватися в різних версіях Python, але два аспекти гарантовано не зміняться:
Якщо додано новий метод посіву, буде запропоновано зворотно сумісний сівалка.
Метод генератора
random()
продовжуватиме створювати ту саму послідовність, коли сумісному розсівачу буде надано те саме початкове значення.
Приклади¶
Основні приклади:
>>> 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
Приклад статистичного завантаження з використанням повторної вибірки із заміною для оцінки довірчого інтервалу для середнього значення вибірки:
# 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}')
Приклад перестановочного тесту повторної вибірки для визначення статистичної значущості або 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.')
Симуляція часу прибуття та надання послуг для багатосерверної черги:
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 зі статистичного аналізу з використанням лише кількох фундаментальних концепцій, включаючи моделювання, вибірку, перетасування та перехресну перевірку.
Economics Simulation a simulation of a marketplace by Peter Norvig that shows effective use of many of the tools and distributions provided by this module (gauss, uniform, sample, betavariate, choice, triangular, and randrange).
A Concrete Introduction to Probability (using Python) a tutorial by Peter Norvig covering the basics of probability theory, how to write simulations, and how to perform data analysis using Python.
рецепти¶
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):
"Choose r elements with replacement. Order the result to match the iterable."
# Result will be in set(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)
За умовчанням random()
повертає кратні 2⁻⁵³ у діапазоні 0,0 ≤ x < 1,0. Усі такі числа розташовані на рівних інтервалах і точно представлені як плаваючі числа Python. Однак багато інших репрезентованих плаваючих значень у цьому інтервалі не є можливим вибором. Наприклад, 0,05954861408025609
не є цілим числом, кратним 2⁻⁵³.
Наступний рецепт передбачає інший підхід. Усі плаваючі значення в інтервалі є можливими виборами. Мантиса походить від рівномірного розподілу цілих чисел у діапазоні 2⁵² ≤ мантиса < 2⁵³. Показник степеня походить із геометричного розподілу, де показники степеня, менші за -53, зустрічаються вдвічі рідше, ніж наступний більший показник степеня.
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)
Усі дійсні розподіли у класі використовуватимуть новий метод:
>>> fr = FullRandom()
>>> fr.random()
0.05954861408025609
>>> fr.expovariate(0.25)
8.87925541791544
Рецепт концептуально еквівалентний алгоритму, який вибирає з усіх кратних 2⁻¹⁰⁷⁴ у діапазоні 0,0 ≤ x < 1,0. Усі такі числа розташовані рівномірно, але більшість із них має бути округлено до найближчого числа з плаваючою точкою, яке можна представити Python. (Значення 2⁻¹⁰⁷⁴ є найменшим позитивним ненормалізованим числом із плаваючою точкою та дорівнює math.ulp(0.0)
.)
Дивись також
Generating Pseudo-random Floating-Point Values стаття Аллена Б. Дауні, яка описує способи генерації більш дрібнозернистих значень з плаваючою комою, ніж зазвичай генерує random()
.