Сообщить об ошибке.

Рецепты использования модуля random в Python

По умолчанию функция random.random() возвращает числа, кратные 2-53, в диапазоне 0.0 ≤ x < 1.0. Все такие числа расположены через равные промежутки и могут быть точно представлены как числа Python с плавающей запятой. Однако многие другие представимые числа float в этом интервале не могут быть выбраны. Например 0,05954861408025609 не является целым числом, кратным 2-53.

В следующем рецепте применения модуля random используется другой подход. Возможны все вещественные числа в интервале. Мантисса исходит из равномерного распределения целых чисел в диапазоне 2-53mantissa < 2-53. Показатель степени получается из геометрического распределения, в котором показатели меньше -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-1074 в диапазоне 0.0 ≤ x < 1.0. Все такие числа равномерно распределены, но большинство из них необходимо округлить до ближайшего представимого числа с плавающей запятой Python. Значение 2-1074 является наименьшим положительным ненормализованным числом с плавающей запятой и равно math.ulp(0.0).