random — Генерация псевдослучайных чисел
Исходный код: Lib/random.py
Этот модуль реализует генераторы псевдослучайных чисел для различных распределений.
Для целых чисел существует равномерный выбор из диапазона. Для последовательностей существует равномерный выбор случайного элемента, функция для генерации случайной перестановки списка на месте и функция для случайной выборки без повторений.
На вещественной оси существуют функции для вычисления равномерного, нормального (гауссова), логарифмически нормального, отрицательно экспоненциального, гамма и бета распределений. Для генерации распределений углов доступно распределение Винье.
Практически все функции модуля зависят от базовой функции random(), которая генерирует случайное число с плавающей запятой равномерно в полуоткрытом интервале [0.0, 1.0). Python использует генератор Мерсенна-Твистер в качестве основного генератора. Он производит числа с плавающей запятой с точностью 53 бита и имеет период 2**19937-1. Базовая реализация на C быстрая и потокобезопасная. Генератор Мерсенна-Твистер является одним из наиболее широко проверенных генераторов псевдослучайных чисел. Однако, будучи полностью детерминированным, он не подходит для всех целей и совершенно непригоден для криптографических целей.
Функции, предоставляемые этим модулем, фактически являются методами связанными с скрытым экземпляром класса random.Random. Вы можете создать свои экземпляры Random, чтобы получить генераторы, которые не разделяют состояние.
Класс Random также может быть расширен, если вы хотите использовать другой базовый генератор по своему выбору: в этом случае переопределите методы random(), seed(), getstate(), и setstate(). При необходимости новый генератор может предоставить метод getrandbits(), что позволит randrange() производить выборки по произвольно большому диапазону.
Модуль random также предоставляет класс SystemRandom, который использует системную функцию os.urandom() для генерации случайных чисел из источников, предоставляемых операционной системой.
Предупреждение
Генераторы псевдослучайных чисел этого модуля не должны использоваться в целях безопасности. Для использования в целях безопасности или криптографии см. модуль secrets.
См. также
М. Мацумото и Т. Нисимура, «Mersenne Twister: A 623-dimensionally equidistributed uniform pseudorandom number generator», ACM Transactions on Modeling and Computer Simulation Том 8, № 1, январь стр. 3–30 1998.
Рецепт Complementary-Multiply-with-Carry для совместимой альтернативы генератора псевдослучайных чисел с большим периодом и сравнительно простыми операциями обновления.
Функции учета
-
random.seed(a=None, version=2) -
Инициализирует генератор случайных чисел.
Если a опущено или
None, используется текущее системное время. Если источники случайности предоставляются операционной системой, они используются вместо системного времени (см. функциюos.urandom()для получения сведений о наличии).Если a является целым числом, оно используется непосредственно.
С версией 2 (по умолчанию), объект
str,bytesилиbytearrayпреобразуется вintи используются все его биты.С версией 1 (предоставленной для воспроизведения случайных последовательностей из более ранних версий Python), алгоритм для
strиbytesгенерирует более узкий диапазон семян.Изменено в версии 3.2: Переведено на схему версии 2, которая использует все биты в строковом семени.
-
random.getstate() -
Возвращает объект, сохраняющий текущее внутреннее состояние генератора. Этот объект может быть передан в
setstate()для восстановления состояния.
-
random.setstate(state) -
state должен был быть получен из предыдущего вызова
getstate(), иsetstate()восстанавливает внутреннее состояние генератора до того состояния, в котором оно было в момент вызоваgetstate().
-
random.getrandbits(k) -
Возвращает целое число Python с k случайными битами. Этот метод поставляется с генератором MersenneTwister, и некоторые другие генераторы также могут его предоставить как необязательную часть API. Когда доступен,
getrandbits()позволяетrandrange()обрабатывать произвольно большие диапазоны.
Функции для целых чисел
-
random.randrange(stop) -
random.randrange(start, stop[, step]) -
Возвращает случайный элемент из
range(start, stop, step). Это эквивалентноchoice(range(start, stop, step)), но фактически не создаёт объект диапазона.Шаблон позиционных аргументов соответствует
range(). Не следует использовать ключевые аргументы, так как функция может их использовать неожиданным образом.Изменено в версии 3.2:
randrange()более совершенен в отношении производства равномерно распределённых значений. Ранее он использовал стиль, подобныйint(random()*n), что могло привести к незначительно неравномерному распределению.
-
random.randint(a, b) -
Возвращает случайное целое число N такое, что
a <= N <= b. Псевдоним дляrandrange(a, b+1).
Функции для последовательностей
-
random.choice(seq) -
Возвращает случайный элемент из непустой последовательности seq. Если seq пустая, генерирует
IndexError.
-
random.choices(population, weights=None, *, cum_weights=None, k=1) -
Возвращает список размером k, выбранный из population с заменой. Если population пуста, генерирует
IndexError.Если указана последовательность weights, выборки производятся в соответствии с относительными весами. В качестве альтернативы, если задана последовательность cum_weights, выборки производятся в соответствии с кумулятивными весами (возможно, вычисленные с помощью
itertools.accumulate()). Например, относительные веса[10, 5, 30, 5]эквивалентны кумулятивным весам[10, 15, 45, 50]. Внутренне относительные веса преобразуются в кумулятивные веса перед выбором, поэтому предоставление кумулятивных весов экономит вычисления.Если ни weights, ни cum_weights не указаны, выборки производятся с равной вероятностью. Если задана последовательность весов, она должна быть того же размера, что и последовательность population. Указание и weights и cum_weights является ошибкой
TypeError.weights или cum_weights могут использовать любой числовой тип, который взаимодействует со значениями с плавающей запятой
float, возвращаемыми модулемrandom()(включая целые числа, числа с плавающей точкой и дроби, но исключая десятичные дроби).Для заданного семени, функция
choices()с равномерным весом обычно генерирует другую последовательность, чем повторные вызовыchoice(). Алгоритм, используемыйchoices(), использует арифметику с плавающей запятой для внутренней согласованности и скорости. Алгоритм, используемыйchoice(), по умолчанию использует целочисленную арифметику с повторными выборками для предотвращения небольших искажений от ошибок округления.Добавлена в версии 3.6.
-
random.shuffle(x[, random]) -
Перемешать последовательность x на месте.
Необязательный аргумент random — это функция без аргументов, возвращающая случайное число с плавающей запятой в интервале [0.0, 1.0); по умолчанию это функция
random().Чтобы перемешать неизменяемую последовательность и вернуть новый перемешанный список, используйте
sample(x, k=len(x))вместо этого.Обратите внимание, что даже для небольшой
len(x), общее количество перестановок x может быстро стать больше периода большинства генераторов случайных чисел. Это означает, что большинство перестановок длинной последовательности могут никогда не быть сгенерированы. Например, последовательность длиной 2080 — это максимальная длина, которая может поместиться в период генератора случайных чисел Mersenne Twister.
-
random.sample(population, k) -
Возвращает список длины k уникальных элементов, выбранных из последовательности или множества population. Используется для случайной выборки без возврата.
Возвращает новый список, содержащий элементы из population, не изменяя исходную population. Результирующий список отсортирован по порядку выбора, так что все подсписки также будут являться корректными случайными выборками. Это позволяет разделить победителей лотереи (выборка) на победителей главного приза и призёров второго места (подсписки).
Элементы population не обязательно должны быть хешируемыми или уникальными. Если population содержит повторения, каждое повторение является возможным выбором в выборке.
Чтобы выбрать выборку из диапазона целых чисел, используйте объект
range()в качестве аргумента. Это особенно быстро и эффективно по памяти для выборки из большой population:sample(range(10000000), k=60).Если размер выборки больше размера population, поднимается исключение
ValueError.
Распределения вещественных чисел
Следующие функции генерируют определённые распределения вещественных чисел. Параметры функций названы в соответствии с соответствующими переменными в уравнении распределения, как используется в общей математической практике; большинство этих уравнений можно найти в любом статистическом учебнике.
-
random.random() -
Возвращает следующее случайное число с плавающей запятой в диапазоне [0.0, 1.0).
-
random.uniform(a, b) -
Возвращает случайное число с плавающей запятой N такое, что
a <= N <= bдляa <= bиb <= N <= aдляb < a.Значение конечной точки
bможет или не может быть включено в диапазон в зависимости от округления чисел с плавающей запятой в уравненииa + (b-a) * random().
-
random.triangular(low, high, mode) -
Возвращает случайное число с плавающей запятой N такое, что
low <= N <= highи с заданной mode между этими границами. Границы low и high по умолчанию равны нулю и единице. Аргумент mode по умолчанию равен середине между границами, что даёт симметричное распределение.
-
random.betavariate(alpha, beta) -
Распределение бета. Условия на параметры —
alpha > 0иbeta > 0. Возвращаемые значения лежат в диапазоне от 0 до 1.
-
random.expovariate(lambd) -
Экспоненциальное распределение. lambd — это 1, делённое на желаемое среднее значение. Оно должно быть ненулевым. (Параметр был бы назван «лямбда», но это зарезервированное слово в Python.) Возвращаемые значения находятся в диапазоне от 0 до положительной бесконечности, если lambd положительно, и от отрицательной бесконечности до 0, если lambd отрицательно.
-
random.gammavariate(alpha, beta) -
Распределение гамма. (Не гамма-функция!) Условия на параметры —
alpha > 0иbeta > 0.Функция плотности вероятности:
x ** (alpha - 1) * math.exp(-x / beta) pdf(x) = -------------------------------------- math.gamma(alpha) * beta ** alpha
-
random.gauss(mu, sigma) -
Гауссово распределение. mu — среднее, а sigma — стандартное отклонение. Это немного быстрее, чем функция
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) -
Распределение Парето. alpha — параметр формы.
-
random.weibullvariate(alpha, beta) -
Распределение Вейбулла. alpha — параметр масштаба, а beta — параметр формы.
Альтернативный генератор
-
class random.Random([seed]) -
Класс, реализующий по умолчанию генератор псевдослучайных чисел, используемый модулем
random.
-
class random.SystemRandom([seed]) -
Класс, использующий функцию
os.urandom()для генерации случайных чисел из источников, предоставляемых операционной системой. Не доступен на всех системах. Не зависит от состояния программного обеспечения, и последовательности не воспроизводимы. Соответственно, методseed()не имеет эффекта и игнорируется. Методыgetstate()иsetstate()поднимают исключениеNotImplementedError, если вызываются.
Примечания о воспроизводимости
Иногда бывает полезно иметь возможность воспроизводить последовательности, генерируемые генератором псевдослучайных чисел. Используя повторное значение семян, та же последовательность должна быть воспроизводимой от запуска к запуску, пока не работают несколько потоков.
Большинство алгоритмов и функций инициализации семян модуля random могут изменяться в разных версиях 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
>>> # (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
Пример статистического бутстрапинга с использованием повторной выборки с возвращением для оценки доверительного интервала для среднего значения выборки размера пять:
# 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}')
Пример перестановки ресемплирования, чтобы определить статистическую значимость или p-значение наблюдаемой разницы между эффектами лекарства и плацебо:
# 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.')
Моделирование времен прихода и выполнения услуг в очереди с одним сервером:
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}.')
См. также
Statistics for Hackers учебное видео Джека Вандерпласа по статистическому анализу, используя всего несколько фундаментальных концепций, включая моделирование, выборку, перемешивание и перекрёстную проверку.
Моделирование экономики моделирование рынка Питера Норвига, которое демонстрирует эффективное использование многих инструментов и распределений, предоставляемых этим модулем (gauss, uniform, sample, betavariate, choice, triangular и randrange).
Конкретное введение в теорию вероятностей (с использованием Python) учебное пособие Питера Норвига, охватывающее основы теории вероятностей, как писать моделирования и как выполнять анализ данных с помощью Python.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.7/library/random.html