random.md
1> **Источник:** https://python-all.ru/3.9/library/random.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [`random`](https://python-all.ru/3.9/library/random.html#module-random) – Генерация псевдослучайных чисел89**Исходный код:** [Lib/random.py](https://python-all.ru/src/3.9/Lib/random.py)1011---1213Этот модуль реализует генераторы псевдослучайных чисел для различных распределений.1415Для целых чисел есть равномерный выбор из диапазона. Для последовательностей есть равномерный выбор случайного элемента, функция для генерации случайной перестановки списка на месте и функция для случайной выборки без возвращения.1617На вещественной прямой есть функции для вычисления равномерного, нормального (гауссовского), логнормального, отрицательного экспоненциального, гамма и бета распределений. Для генерации распределений углов доступно распределение фон Мизеса.1819Почти все функции модуля зависят от базовой функции [`random()`](https://python-all.ru/3.9/library/random.html#random.random), которая генерирует случайное число с плавающей запятой, равномерно распределённое в полуоткрытом диапазоне \[0.0, 1.0). Python использует вихрь Мерсенна в качестве основного генератора. Он выдаёт числа с плавающей запятой точностью 53 бита и имеет период 2\*\*19937-1. Базовая реализация на C быстра и потокобезопасна. Вихрь Мерсенна – один из наиболее тщательно протестированных генераторов случайных чисел. Однако, будучи полностью детерминированным, он не подходит для всех целей и совершенно непригоден для криптографии.2021Функции, предоставляемые этим модулем, на самом деле являются привязанными методами скрытого экземпляра класса [`random.Random`](https://python-all.ru/3.9/library/random.html#random.Random). Можно создать собственные экземпляры [`Random`](https://python-all.ru/3.9/library/random.html#random.Random), чтобы получить генераторы, не разделяющие состояние.2223Класс [`Random`](https://python-all.ru/3.9/library/random.html#random.Random) также можно наследовать, если требуется использовать другой базовый генератор собственной разработки: в этом случае необходимо переопределить методы `random()`, `seed()`, `getstate()` и `setstate()`. При необходимости новый генератор может предоставить метод `getrandbits()` – это позволяет [`randrange()`](https://python-all.ru/3.9/library/random.html#random.randrange) производить выборки из произвольно большого диапазона.2425Модуль [`random`](https://python-all.ru/3.9/library/random.html#module-random) также предоставляет класс [`SystemRandom`](https://python-all.ru/3.9/library/random.html#random.SystemRandom), который использует системную функцию [`os.urandom()`](https://python-all.ru/3.9/library/os.html#os.urandom) для генерации случайных чисел из источников, предоставляемых операционной системой.2627> **Предупреждение**28>29> Псевдослучайные генераторы этого модуля не следует использовать для целей безопасности. Для безопасности или криптографического использования см. модуль [`secrets`](https://python-all.ru/3.9/library/secrets.html#module-secrets).3031> **См. также**32>33> М. Мацумото и Т. Нисимура, «Вихрь Мерсенна: 623-мерно равномерно распределенный генератор псевдослучайных чисел», ACM Transactions on Modeling and Computer Simulation том 8, № 1, январь, стр. 3–30, 1998.34>35> [Complementary-Multiply-with-Carry recipe](https://python-all.ru/3.9/library/random.html) для совместимого альтернативного генератора случайных чисел с длинным периодом и сравнительно простыми операциями обновления.3637## Учётные функции3839#### `random.seed(a=None, version=2)`4041Инициализирует генератор случайных чисел.4243Если *a* опущен или равен `None`, используется текущее системное время. Если источники случайности предоставляются операционной системой, они используются вместо системного времени (см. функцию [`os.urandom()`](https://python-all.ru/3.9/library/os.html#os.urandom) для получения подробной информации о доступности).4445Если *a* – целое число, оно используется напрямую.4647В версии 2 (по умолчанию) объект [`str`](https://python-all.ru/3.9/library/stdtypes.html#str), [`bytes`](https://python-all.ru/3.9/library/stdtypes.html#bytes) или [`bytearray`](https://python-all.ru/3.9/library/stdtypes.html#bytearray) преобразуется в [`int`](https://python-all.ru/3.9/library/functions.html#int) и используются все его биты.4849В версии 1 (предназначенной для воспроизведения случайных последовательностей из старых версий Python) алгоритм для [`str`](https://python-all.ru/3.9/library/stdtypes.html#str) и [`bytes`](https://python-all.ru/3.9/library/stdtypes.html#bytes) генерирует более узкий диапазон начальных значений (семян).5051Изменено в версии 3.2: Переход на схему версии 2, которая использует все биты строкового начального значения.5253Устарело с версии 3.9: В будущем *seed* должен быть одним из следующих типов: *NoneType*, [`int`](https://python-all.ru/3.9/library/functions.html#int), [`float`](https://python-all.ru/3.9/library/functions.html#float), [`str`](https://python-all.ru/3.9/library/stdtypes.html#str), [`bytes`](https://python-all.ru/3.9/library/stdtypes.html#bytes) или [`bytearray`](https://python-all.ru/3.9/library/stdtypes.html#bytearray).5455#### `random.getstate()`5657Возвращает объект, фиксирующий текущее внутреннее состояние генератора. Этот объект можно передать в [`setstate()`](https://python-all.ru/3.9/library/random.html#random.setstate) для восстановления состояния.5859#### `random.setstate(state)`6061*state* должен быть получен из предыдущего вызова [`getstate()`](https://python-all.ru/3.9/library/random.html#random.getstate), а [`setstate()`](https://python-all.ru/3.9/library/random.html#random.setstate) восстанавливает внутреннее состояние генератора в то, которое было на момент вызова [`getstate()`](https://python-all.ru/3.9/library/random.html#random.getstate).6263## Функции для байтов6465#### `random.randbytes(n)`6667Генерирует *n* случайных байтов.6869Этот метод не следует использовать для генерации токенов безопасности. Вместо этого используйте [`secrets.token_bytes()`](https://python-all.ru/3.9/library/secrets.html#secrets.token_bytes).7071Новое в версии 3.9.7273## Функции для целых чисел7475#### `random.randrange(stop)`7677#### `random.randrange(start, stop[, step])`7879Возвращает случайно выбранный элемент из `range(start, stop, step)`. Это равнозначно `choice(range(start, stop, step))`, но на самом деле не создаёт объект range.8081Шаблон позиционных аргументов совпадает с шаблоном [`range()`](https://python-all.ru/3.9/library/stdtypes.html#range). Именованные аргументы не следует использовать, поскольку функция может применить их неожиданным образом.8283Изменено в версии 3.2: [`randrange()`](https://python-all.ru/3.9/library/random.html#random.randrange) стала более совершенной в генерации равномерно распределённых значений. Ранее использовался подход, подобный `int(random()*n)`, который мог давать несколько неравномерные распределения.8485#### `random.randint(a, b)`8687Возвращает случайное целое *N* такое, что `a <= N <= b`. Псевдоним для `randrange(a, b+1)`.8889#### `random.getrandbits(k)`9091Возвращает неотрицательное целое число Python с *k* случайными битами. Этот метод предоставляется генератором MersenneTwister, и некоторые другие генераторы могут также предоставлять его как опциональную часть API. Когда доступен, [`getrandbits()`](https://python-all.ru/3.9/library/random.html#random.getrandbits) позволяет [`randrange()`](https://python-all.ru/3.9/library/random.html#random.randrange) обрабатывать произвольно большие диапазоны.9293Изменено в версии 3.9: Этот метод теперь принимает ноль для *k*.9495## Функции для последовательностей9697#### `random.choice(seq)`9899Возвращает случайный элемент из непустой последовательности *seq*. Если *seq* пуста, возбуждает [`IndexError`](https://python-all.ru/3.9/library/exceptions.html#IndexError).100101#### `random.choices(population, weights=None, *, cum_weights=None, k=1)`102103Возвращает список размера *k* из элементов, выбранных из *population* с возвращением. Если *population* пуста, возбуждает [`IndexError`](https://python-all.ru/3.9/library/exceptions.html#IndexError).104105Если задана последовательность *weights*, выборки производятся в соответствии с относительными весами. Альтернативно, если задана последовательность *cum\_weights*, выборки производятся по накопленным весам (возможно, вычисленным с помощью [`itertools.accumulate()`](https://python-all.ru/3.9/library/itertools.html#itertools.accumulate)). Например, относительные веса `[10, 5, 30, 5]` эквивалентны накопленным весам `[10, 15, 45, 50]`. Внутренне относительные веса преобразуются в накопленные перед выполнением выборок, поэтому передача накопленных весов экономит работу.106107Если не указаны ни *weights*, ни *cum\_weights*, выборки производятся с равной вероятностью. Если передана последовательность весов, её длина должна равняться длине последовательности *population*. Указание и *weights*, и *cum\_weights* приводит к [`TypeError`](https://python-all.ru/3.9/library/exceptions.html#TypeError).108109*weights* или *cum\_weights* могут использовать любой числовой тип, совместимый со значениями [`float`](https://python-all.ru/3.9/library/functions.html#float), возвращаемыми [`random()`](https://python-all.ru/3.9/library/random.html#module-random) (включая целые числа, числа с плавающей точкой и дроби, но не десятичные числа). Поведение не определено, если какой-либо вес отрицателен. Исключение [`ValueError`](https://python-all.ru/3.9/library/exceptions.html#ValueError) возникает, если все веса равны нулю.110111Для заданного начального значения функция [`choices()`](https://python-all.ru/3.9/library/random.html#random.choices) с равными весами обычно порождает другую последовательность, чем повторные вызовы [`choice()`](https://python-all.ru/3.9/library/random.html#random.choice). Алгоритм, используемый [`choices()`](https://python-all.ru/3.9/library/random.html#random.choices), применяет арифметику с плавающей точкой для внутренней согласованности и скорости. Алгоритм, используемый [`choice()`](https://python-all.ru/3.9/library/random.html#random.choice), по умолчанию использует целочисленную арифметику с повторными выборками, чтобы избежать небольших смещений из-за ошибок округления.112113Новое в версии 3.6.114115Изменено в версии 3.9: Возбуждает [`ValueError`](https://python-all.ru/3.9/library/exceptions.html#ValueError), если все веса равны нулю.116117#### `random.shuffle(x[, random])`118119Перемешивает последовательность *x* на месте.120121Необязательный аргумент *random* – это функция без аргументов, возвращающая случайное число с плавающей запятой из диапазона \[0.0, 1.0); по умолчанию это функция [`random()`](https://python-all.ru/3.9/library/random.html#random.random).122123Чтобы перемешать неизменяемую последовательность и вернуть новый перемешанный список, используйте `sample(x, k=len(x))`.124125Обратите внимание, что даже для небольших `len(x)` общее число перестановок *x* может быстро превысить период большинства генераторов случайных чисел. Это означает, что большинство перестановок длинной последовательности никогда не могут быть сгенерированы. Например, последовательность длины 2080 – это самая длинная, которая умещается в период генератора случайных чисел Mersenne Twister.126127Устарело с версии 3.9, будет удалено в версии 3.11: Необязательный параметр *random*.128129#### `random.sample(population, k, *, counts=None)`130131Возвращает список длины *k* из уникальных элементов, выбранных из последовательности population или множества. Используется для случайной выборки без возвращения.132133Возвращает новый список, содержащий элементы из population, не изменяя исходную population. Результирующий список упорядочен по порядку выбора, так что все подсписки также будут корректными случайными выборками. Это позволяет разделить победителей розыгрыша (выборку) на обладателей главного и второго призов (подсписки).134135Элементы population не обязаны быть [хэшируемыми](https://python-all.ru/3.9/glossary.html#term-hashable) или уникальными. Если population содержит повторения, то каждое вхождение является возможным элементом выборки.136137Повторяющиеся элементы можно указывать по одному или с помощью необязательного параметра *counts*, передаваемого только по ключу. Например, `sample(['red', 'blue'], counts=[4, 2], k=5)` эквивалентно `sample(['red', 'red', 'red', 'red', 'blue', 'blue'], k=5)`.138139Чтобы выбрать выборку из диапазона целых чисел, используйте объект [`range()`](https://python-all.ru/3.9/library/stdtypes.html#range) в качестве аргумента. Это особенно быстро и эффективно по памяти при выборке из большой популяции: `sample(range(10000000), k=60)`.140141Если размер выборки превышает размер популяции, возбуждается исключение [`ValueError`](https://python-all.ru/3.9/library/exceptions.html#ValueError).142143Изменено в версии 3.9: Добавлен параметр *counts*.144145Устарело с версии 3.9: В будущем *population* должен быть последовательностью. Экземпляры [`set`](https://python-all.ru/3.9/library/stdtypes.html#set) больше не поддерживаются. Множество необходимо предварительно преобразовать в [`list`](https://python-all.ru/3.9/library/stdtypes.html#list) или [`tuple`](https://python-all.ru/3.9/library/stdtypes.html#tuple), желательно с детерминированным порядком, чтобы выборка была воспроизводимой.146147## Вещественные распределения148149Следующие функции генерируют конкретные вещественные распределения. Имена параметров функций соответствуют переменным в уравнении распределения, как принято в математической практике; большинство этих уравнений можно найти в любом учебнике по статистике.150151#### `random.random()`152153Возвращает следующее случайное число с плавающей запятой в диапазоне \[0.0, 1.0).154155#### `random.uniform(a, b)`156157Возвращает случайное число с плавающей точкой *N* такое, что `a <= N <= b` для `a <= b` и `b <= N <= a` для `b < a`.158159Конечное значение `b` может как входить, так и не входить в диапазон в зависимости от округления чисел с плавающей запятой в уравнении `a + (b-a) * random()`.160161#### `random.triangular(low, high, mode)`162163Возвращает случайное число с плавающей точкой *N* такое, что `low <= N <= high` и с заданной *модой* между этими границами. Границы *low* и *high* по умолчанию равны нулю и единице. Аргумент *mode* по умолчанию равен середине между границами, что даёт симметричное распределение.164165#### `random.betavariate(alpha, beta)`166167Бета-распределение. Условия на параметры: `alpha > 0` и `beta > 0`. Возвращаемые значения находятся в диапазоне от 0 до 1.168169#### `random.expovariate(lambd)`170171Экспоненциальное распределение. *lambd* – это 1.0, делённая на желаемое среднее. Оно должно быть ненулевым. (Параметр мог бы называться «lambda», но это зарезервированное слово в Python.) Возвращаемые значения находятся в диапазоне от 0 до положительной бесконечности, если *lambd* положительно, и от отрицательной бесконечности до 0, если *lambd* отрицательно.172173#### `random.gammavariate(alpha, beta)`174175Гамма-распределение. (*Не* гамма-функция!) Условия на параметры: `alpha > 0` и `beta > 0`.176177Функция плотности распределения вероятности:178179```python180 x ** (alpha - 1) * math.exp(-x / beta)181pdf(x) = --------------------------------------182 math.gamma(alpha) * beta ** alpha183```184185#### `random.gauss(mu, sigma)`186187Гауссово распределение. *mu* – математическое ожидание, а *sigma* – стандартное отклонение. Эта функция немного быстрее, чем [`normalvariate()`](https://python-all.ru/3.9/library/random.html#random.normalvariate), определённая ниже.188189Примечание о многопоточности: когда два потока одновременно вызывают эту функцию, они могут получить одно и то же возвращаемое значение. Этого можно избежать тремя способами: 1) Пусть каждый поток использует свой экземпляр генератора случайных чисел. 2) Установите блокировки вокруг всех вызовов. 3) Используйте более медленную, но потокобезопасную функцию [`normalvariate()`](https://python-all.ru/3.9/library/random.html#random.normalvariate).190191#### `random.lognormvariate(mu, sigma)`192193Логнормальное распределение. Если взять натуральный логарифм этого распределения, получится нормальное распределение со средним *mu* и стандартным отклонением *sigma*. *mu* может принимать любое значение, а *sigma* должна быть больше нуля.194195#### `random.normalvariate(mu, sigma)`196197Нормальное распределение. *mu* – это среднее, а *sigma* – стандартное отклонение.198199#### `random.vonmisesvariate(mu, kappa)`200201*mu* – это средний угол, выраженный в радианах от 0 до 2\**pi*, а *kappa* – параметр концентрации, который должен быть больше или равен нулю. Если *kappa* равен нулю, это распределение сводится к равномерному случайному углу в диапазоне от 0 до 2\**pi*.202203#### `random.paretovariate(alpha)`204205Распределение Парето. *alpha* – параметр формы.206207#### `random.weibullvariate(alpha, beta)`208209Распределение Вейбулла. *alpha* – параметр масштаба, а *beta* – параметр формы.210211## Альтернативный генератор212213#### `class random.Random([seed])`214215Класс, реализующий генератор псевдослучайных чисел по умолчанию, используемый модулем [`random`](https://python-all.ru/3.9/library/random.html#module-random).216217Устарело с версии 3.9: в будущем *seed* должен быть одним из следующих типов: `NoneType`, [`int`](https://python-all.ru/3.9/library/functions.html#int), [`float`](https://python-all.ru/3.9/library/functions.html#float), [`str`](https://python-all.ru/3.9/library/stdtypes.html#str), [`bytes`](https://python-all.ru/3.9/library/stdtypes.html#bytes) или [`bytearray`](https://python-all.ru/3.9/library/stdtypes.html#bytearray).218219#### `class random.SystemRandom([seed])`220221Класс, использующий функцию [`os.urandom()`](https://python-all.ru/3.9/library/os.html#os.urandom) для генерации случайных чисел из источников, предоставляемых операционной системой. Доступен не на всех системах. Не зависит от состояния программного обеспечения, и последовательности невоспроизводимы. Соответственно, метод [`seed()`](https://python-all.ru/3.9/library/random.html#random.seed) не действует и игнорируется. Методы [`getstate()`](https://python-all.ru/3.9/library/random.html#random.getstate) и [`setstate()`](https://python-all.ru/3.9/library/random.html#random.setstate) вызывают [`NotImplementedError`](https://python-all.ru/3.9/library/exceptions.html#NotImplementedError) при вызове.222223## Примечания о воспроизводимости224225Иногда бывает полезно иметь возможность воспроизводить последовательности, выдаваемые генератором псевдослучайных чисел. При повторном использовании начального значения одна и та же последовательность должна воспроизводиться от запуска к запуску, если не запущено несколько потоков.226227Большинство алгоритмов и функций инициализации генератора модуля random могут меняться в разных версиях Python, но два аспекта гарантированно остаются неизменными:228229- Если будет добавлен новый метод инициализации, будет предложен обратно совместимый инициализатор.230- Метод `random()` генератора продолжит выдавать ту же последовательность, если совместимому инициализатору передать то же начальное значение.231232## Примеры233234Простые примеры:235236```python237>>> random() # Случайное число с плавающей точкой: 0.0 <= x < 1.02380.37444887175646646239240>>> uniform(2.5, 10.0) # Случайное число с плавающей точкой: 2.5 <= x <= 10.02413.1800146073117523242243>>> expovariate(1 / 5) # Интервал между поступлениями в среднем 5 секунд2445.148957571865031245246>>> randrange(10) # Целое число от 0 до 9 включительно2477248249>>> randrange(0, 101, 2) # Чётное целое число от 0 до 100 включительно25026251252>>> choice(['win', 'lose', 'draw']) # Один случайный элемент из последовательности253'draw'254255>>> deck = 'ace two three four'.split()256>>> shuffle(deck) # Перемешать список257>>> deck258['four', 'two', 'ace', 'three']259260>>> sample([10, 20, 30, 40, 50], k=4) # Четыре выборки без возвращения261[40, 10, 50, 30]262```263264Симуляции:265266```python267>>> # Шесть вращений колеса рулетки (взвешенная выборка с возвращением)268>>> choices(['red', 'black', 'green'], [18, 18, 2], k=6)269['red', 'green', 'black', 'black', 'red', 'black']270271>>> # Раздать 20 карт без возвращения из колоды272>>> # из 52 игральных карт и определить долю карт273>>> # со значением десять: десятка, валет, дама или король.274>>> dealt = sample(['tens', 'low cards'], counts=[16, 36], k=20)275>>> dealt.count('tens') / 202760.15277278>>> # Оценить вероятность выпадения 5 или более орлов за 7 подбрасываний279>>> # несимметричной монеты, которая выпадает орлом в 60% случаев.280>>> def trial():281... return choices('HT', cum_weights=(0.60, 1.00), k=7).count('H') >= 5282...283>>> sum(trial() for i in range(10_000)) / 10_0002840.4169285286>>> # Вероятность того, что медиана 5 выборок окажется в двух средних квартилях287>>> def trial():288... return 2_500 <= sorted(choices(range(10_000), k=5))[2] < 7_500289...290>>> sum(trial() for i in range(10_000)) / 10_0002910.7958292```293294Пример [статистического бутстрепа](https://python-all.ru/3.9/library/random.html) с использованием повторной выборки с возвращением для оценки доверительного интервала для среднего значения выборки:295296```python297# http://statistics.about.com/od/Applications/a/Example-Of-Bootstrapping.htm298from statistics import fmean as mean299from random import choices300301data = [41, 50, 29, 37, 81, 30, 73, 63, 20, 35, 68, 22, 60, 31, 95]302means = sorted(mean(choices(data, k=len(data))) for i in range(100))303print(f'The sample mean of {mean(data):.1f} has a 90% confidence '304 f'interval from {means[5]:.1f} to {means[94]:.1f}')305```306307Пример [пермутационного теста с повторной выборкой](https://python-all.ru/3.9/library/random.html) для определения статистической значимости или [p-значения](https://python-all.ru/3.9/library/random.html) наблюдаемого различия между эффектами препарата и плацебо:308309```python310# Пример из книги "Statistics is Easy" Денниса Шаши и Манды Уилсон311from statistics import fmean as mean312from random import shuffle313314drug = [54, 73, 53, 70, 73, 68, 52, 65, 65]315placebo = [54, 51, 58, 44, 55, 52, 42, 47, 58, 46]316observed_diff = mean(drug) - mean(placebo)317318n = 10_000319count = 0320combined = drug + placebo321for i in range(n):322 shuffle(combined)323 new_diff = mean(combined[:len(drug)]) - mean(combined[len(drug):])324 count += (new_diff >= observed_diff)325326print(f'{n} label reshufflings produced only {count} instances with a difference')327print(f'at least as extreme as the observed difference of {observed_diff:.1f}.')328print(f'The one-sided p-value of {count / n:.4f} leads us to reject the null')329print(f'hypothesis that there is no difference between the drug and the placebo.')330```331332Моделирование времени поступления и обслуживания запросов для многоканальной очереди:333334```python335from heapq import heapify, heapreplace336from random import expovariate, gauss337from statistics import mean, median, stdev338339average_arrival_interval = 5.6340average_service_time = 15.0341stdev_service_time = 3.5342num_servers = 3343344waits = []345arrival_time = 0.0346servers = [0.0] * num_servers # время, когда каждый сервер становится доступным347heapify(servers)348for i in range(1_000_000):349 arrival_time += expovariate(1.0 / average_arrival_interval)350 next_server_available = servers[0]351 wait = max(0.0, next_server_available - arrival_time)352 waits.append(wait)353 service_duration = max(0.0, gauss(average_service_time, stdev_service_time))354 service_completed = arrival_time + wait + service_duration355 heapreplace(servers, service_completed)356357print(f'Mean wait: {mean(waits):.1f}. Stdev wait: {stdev(waits):.1f}.')358print(f'Median wait: {median(waits):.1f}. Max wait: {max(waits):.1f}.')359```360361> **См. также**362>363> [Statistics for Hackers](https://python-all.ru/3.9/library/random.html) – видеоурок от [Jake Vanderplas](https://python-all.ru/3.9/library/random.html) по статистическому анализу, использующему всего несколько фундаментальных понятий, включая моделирование, выборку, перемешивание и кросс-валидацию.364>365> [Economics Simulation](https://python-all.ru/3.9/library/random.html) – симуляция рынка от [Peter Norvig](https://python-all.ru/3.9/library/random.html), демонстрирующая эффективное использование многих инструментов и распределений, предоставляемых этим модулем (gauss, uniform, sample, betavariate, choice, triangular и randrange).366>367> [A Concrete Introduction to Probability (using Python)](https://python-all.ru/3.9/library/random.html) – учебное пособие от [Peter Norvig](https://python-all.ru/3.9/library/random.html), охватывающее основы теории вероятностей, написание симуляций и выполнение анализа данных с помощью Python.368369## Рецепты370371По умолчанию [`random()`](https://python-all.ru/3.9/library/random.html#random.random) возвращает числа, кратные 2⁻⁵³, в диапазоне *0.0 ≤ x \< 1.0*. Все такие числа равномерно распределены и точно представимы как числа с плавающей запятой Python. Однако многие другие представимые числа с плавающей запятой в этом интервале не могут быть выбраны. Например, `0.05954861408025609` не является целым кратным 2⁻⁵³.372373Следующий рецепт использует другой подход. Все числа с плавающей запятой в интервале могут быть выбраны. Мантисса берётся из равномерного распределения целых чисел в диапазоне *2⁵² ≤ mantissa \< 2⁵³*. Показатель степени берётся из геометрического распределения, где показатели меньше *-53* встречаются вдвое реже, чем следующий больший показатель.374375```python376from random import Random377from math import ldexp378379class FullRandom(Random):380381 def random(self):382 mantissa = 0x10_0000_0000_0000 | self.getrandbits(52)383 exponent = -53384 x = 0385 while not x:386 x = self.getrandbits(32)387 exponent += x.bit_length() - 32388 return ldexp(mantissa, exponent)389```390391Все [вещественнозначные распределения](https://python-all.ru/3.9/library/random.html#real-valued-distributions) в классе будут использовать новый метод:392393```python394>>> fr = FullRandom()395>>> fr.random()3960.05954861408025609397>>> fr.expovariate(0.25)3988.87925541791544399```400401Этот рецепт концептуально эквивалентен алгоритму, который выбирает из всех чисел, кратных 2⁻¹⁰⁷⁴, в диапазоне *0.0 ≤ x \< 1.0*. Все такие числа равномерно распределены, но большинство приходится округлять вниз до ближайшего представимого числа с плавающей запятой Python. (Значение 2⁻¹⁰⁷⁴ – это наименьшее положительное ненормализованное число с плавающей запятой, равное `math.ulp(0.0)`.)402403> **См. также**404>405> [Generating Pseudo-random Floating-Point Values](https://python-all.ru/3.9/library/random.html) – статья Аллена Б. Дауни, описывающая способы генерации более мелкозернистых чисел с плавающей запятой, чем обычно генерирует [`random()`](https://python-all.ru/3.9/library/random.html#random.random).406