Spec-Zone.ru › Python 3.7

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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API