random — Генерация псевдослучайных чисел
Исходный код: Lib/random.py
Этот модуль реализует генераторы псевдослучайных чисел для различных распределений.
Для целых чисел осуществляется равномерный выбор из диапазона. Для последовательностей существует равномерный выбор случайного элемента, функция для генерации случайной перестановки списка на месте и функция для случайной выборки без повторения.
На вещественной прямой существуют функции для вычисления равномерного, нормального (гауссового), логнормального, отрицательного экспоненциального, гамма и бета-распределений. Для генерации распределений углов доступно распределение Винера.
Практически все функции модуля зависят от основной функции random(), которая генерирует случайное вещественное число равномерно в полуоткрытом диапазоне [0.0, 1.0). Python использует генератор Мерсенна-Твистер в качестве основного генератора. Он производит числа с плавающей точкой с 53-битной точностью и имеет период 219937-1. Подлежащая реализация на C быстрая и потокобезопасная. Генератор Мерсенна-Твистер является одним из наиболее тщательно протестированных генераторов псевдослучайных чисел, которые существуют. Однако, будучи полностью детерминированным, он не подходит для всех целей и совершенно непригоден для криптографических целей.
Функции, предоставляемые этим модулем, фактически являются связанными методами скрытого экземпляра класса random.Random. Вы можете создать свои экземпляры класса Random, чтобы получить генераторы, которые не разделяют состояние.
Класс Random также может быть расширен, если вы хотите использовать другой базовый генератор собственной разработки: в этом случае переопределите методы random(), seed(), getstate(), и setstate(). При необходимости новый генератор может предоставить метод getrandbits() — это позволяет randrange() производить выбор в произвольно большом диапазоне.
Модуль random также предоставляет класс SystemRandom, который использует системную функцию os.urandom() для генерации случайных чисел из источников, предоставляемых операционной системой.
Предупреждение
Генераторы псевдослучайных чисел этого модуля не должны использоваться в целях безопасности. Для использования в целях безопасности или криптографии см. модуль secrets.
См. также
М. Мацумото и Т. Нисимура, «Генератор псевдослучайных чисел Мерсенна-Твистер: 623-мерно равнораспределенный генератор псевдослучайных чисел», 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 случайными битами. Этот метод поставляется с генератором Мерсенна-Твистер, и некоторые другие генераторы также могут предоставить его как необязательную часть 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 не указаны, выбор элементов происходит с равной вероятностью. Если указана последовательность 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 содержит повторы, то каждое вхождение является возможным выбором в sample.
Чтобы выбрать выборку из диапазона целых чисел, используйте объект
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.0, делённому на желаемое среднее значение. Оно должно быть отличным от нуля. (Параметр назывался бы «лямбда», но это зарезервированное слово в 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(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
Пример статистического бутстрапа с использованием ресемплирования с возвращением для оценки доверительного интервала для среднего значения выборки:
# http://statistics.about.com/od/Applications/a/Example-Of-Bootstrapping.htm
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 heappush, heappop
from random import expovariate, gauss
from statistics import mean, median, stdev
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
for i in range(100_000):
arrival_time += expovariate(1.0 / average_arrival_interval)
next_server_available = heappop(servers)
wait = max(0.0, next_server_available - arrival_time)
waits.append(wait)
service_duration = gauss(average_service_time, stdev_service_time)
service_completed = arrival_time + wait + service_duration
heappush(servers, service_completed)
print(f'Mean wait: {mean(waits):.1f}. Stdev wait: {stdev(waits):.1f}.')
print(f'Median wait: {median(waits):.1f}. Max wait: {max(waits):.1f}.')
См. также
Статистика для хакеров — видео-учебник Джека Вандерпласа по статистическому анализу с использованием нескольких основных концепций, включая моделирование, выборку, перемешивание и перекрестную проверку.
Моделирование экономики — моделирование рынка, созданное Питером Норвигом, демонстрирующее эффективное использование многих инструментов и распределений из этого модуля (gauss, uniform, sample, betavariate, choice, triangular и randrange).
Конкретное введение в теорию вероятностей (с использованием Python) — учебник Питера Норвига, охватывающий основы теории вероятностей, как создавать модели, а также как проводить анализ данных с помощью Python.
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/random.html