# `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, яка використовує всі біти початкового рядка.

  Змінено в версії 3.11: The seed must be one of the following types: `None`, `int`, `float`, `str`, `bytes`, or `bytearray`.

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 to `choice(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 to `randrange(10)`. In the future, this will raise a `TypeError`.

  Застаріло починаючи з версії 3.10: The exception raised for non-integer values such as `randrange(10.5)` or `randrange('10')` will be changed from `ValueError` to `TypeError`.

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()` enables `randrange()` 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 to `choice()`. The algorithm used by `choices()` uses floating point arithmetic for internal consistency and speed. The algorithm used by `choice()` 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` for `a <= b` and `b <= N <= a` for `b < a`.

  The end-point value `b` may or may not be included in the range depending on floating-point rounding in the expression `a + (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`, or `bytearray`.

  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 of `Random` instances.

  getstate()

    Override this method in subclasses to customise the `getstate()` behaviour of `Random` instances.

  setstate(state)

    Override this method in subclasses to customise the `setstate()` behaviour of `Random` instances.

  random()

    Override this method in subclasses to customise the `random()` behaviour of `Random` instances.

  Optionally, a custom generator subclass can also supply the following method:

  getrandbits(k)

    Override this method in subclasses to customise the `getrandbits()` behaviour of `Random` 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()`.