Модуль Random для генерации случайных чисел в Python

Время от времени программистам необходимо генерировать случайные числа. Для этого используется специальный модуль Python –  Random. Конечно, он не создает истинно случайные значения, поскольку это технически невозможно реализовать. Но псевдослучайные он генерировать вполне способен. 

Он имеет некоторые особенности:

  1. Если число целое, то доступен выбор одного из диапазона.
  2. Если мы работаем с последовательностями, то доступен выбор случайного элемента, случайная сортировка списка, функция случайного выбора из нескольких элементов, и так далее. 
  3. Имеются функции, с помощью которых вычисляются однородные и нормальные распределения. Также есть возможности вычисления логнормальных, отрицательных, экспоненциальных, гамма и бета распределений.
  4. Есть также распределение фон Мизеса, чтобы генерировать распределения углов.

Независимо от того, какая функция используется, она зависит от базовой функции random(). А ее работа простая – генерировать случайным образом число с плавающей точкой (при этом после запятой может стоять 0). Для упрощения будем дальше использовать понятие float.

В качестве генератора используется Mersenne Twister. Он создает 53-битные числа с плавающей точкой. Его реализация быстрая и многопоточная. Из всех генераторов случайных чисел его протестировало самое большое количество людей. Правда, не для всех целей его можно использовать. В частности, он не подходит для криптографии, поскольку не является полностью детерминированным. 

С помощью модуля Random также можно генерировать случайные числа из операционной системы. Для этого используется системная функция os.urandom(), которая относится к классу SystemRandom. 

Внимание! Псевдослучайные генераторы ни в коем случае не могут использоваться для обеспечения безопасности. Для этого используется совсем другой модуль – secrets.

Функции для целых чисел

Теперь давайте перейдем непосредственно к рассмотрению функций для целых чисел. Первая из них – random.randrange(stop) или random.randrange(start, stop, [step]). Это базовая функция, которая возвращает случайное число из указанного пользователем диапазона с учетом шага. 

Аргументы функции:

  1. Start – первое число диапазона.
  2. Stop – последнее число диапазона. 
  3. Step – шаг, с которым осуществляется перебор значений, из которых будет выбрано случайное число. 

Давайте теперь приведем пример фрагмента кода, как это реализуется на практике (вместе с выводом).

>>> random.randrange(0, 101, 2)

26

Видите, что шаблон позиционного аргумента такой же самый, как и range() имеет.

Следующая функция – random.randint(a,b). Она отвечает за генерацию целочисленного значения. При генерации соблюдается правило, что a <= N <= b.

Давайте посмотрим на пример использования этой функции. 

>>> random.randint(0, 101)

44

Функции, используемые в последовательностях

random.choice(seq). С помощью этой функции мы получаем случайный элемент из непустой последовательности seq. В качестве такой может использоваться, например, список. Если же в качестве аргумента передается пустая последовательность, то тогда выдается ошибка IndexError.

>>> choice([‘win’, ‘lose’, ‘draw’])

‘draw’

random.choices(population, weights=None, *, cum_weights=None, k=1). Используется для генерации элементов с заменой. Они отбираются из аргумента population. Если же этот аргумент пуст, возникает та же ошибка, что и в прошлом методе. 

>>> random.choices([«яблоки», «бананы», «вишня»], weights = [10, 1, 1], k = 5)

[‘яблоки’, ‘вишня’, ‘яблоки’, ‘яблоки’, ‘яблоки’]

Если есть последовательность weights, то при выборе учитывается относительный вес. Если задана последовательность cum_weights, то выбор также может осуществляться, основываясь на совокупных весах. Например, рассчитываться, исходя из itertools.accumulate().

Допустим, относительный вес [10, 5, 30, 5] эквивалентен кумулятивному [10, 15, 45, 50]. Внутренне относительные веса конвертируются в кумулятивные перед выбором. Это помогает сэкономить время.

Если ни относительный, ни кумулятивный вес не известны, то тогда выбор осуществляется полностью случайно. То есть, каждый элемент последовательности имеет шанс быть выбранным.

random.shuffle(x, [random]). Выполняет перемешивание элементов x на месте. Здесь есть необязательный аргумент random (он выделен квадратными скобками). Он означает функцию 0 аргумента, которая возвращает случайное число с плавающей точкой в [0.0, 1.0]. Если другого не задано, используется функция random()

>>> fruits = ["яблоки", "бананы", "вишня"]

>>> random.shuffle(fruits)

>>> fruits

['бананы', 'вишня', 'яблоки']

Стоит использовать sample(x, k=len(x)), чтобы выполнить перемешивание неизменяемой последовательности и вернуть новый перемешанный список. 

Учитывайте и то, что даже при небольшой длине последовательности общее количество перестановок может быть довольно большим. Простыми словами, большая часть возможных комбинаций никогда не будет выполнена. Например, генератор случайных чисел «Мерсин Твистер» не может перемешивать последовательность длиной больше 2080 элементов. 

random.sample(population, k). Возвращает список длиной, равной числу, указанному в качестве второго аргумента этой функции. А в качестве первого аргумента используется последовательность или множество. Замены не происходит в этом случае. 

>>> random.sample([0, 1, 2, 3, 4, 5, 6], 3)

[5, 6, 4]

Этот список содержит элементы из последовательности, оставляя первоначальную без изменений. Новый список располагается в порядке выбора таким образом, чтобы суб-срезы также являлись случайными последовательностями значений.

Где это может использоваться на практике? Например, в ситуациях, если победителям нужно разделиться на первое, второе места, и так далее. 

Если в последовательность входят повторяющиеся значения, то каждой вхождение может быть выбранным генератором. Для выбора одного числа из набора, необходимо в качестве аргумента использовать функцию range(). Ее синтаксис вам знаком. 

Если нам необходимо передать методу большую выборку, можно воспользоваться этим примером (вставив в качестве первого аргумента свое число).

sample(range(10000000), k=60)

Если величина выборки превышает длину последовательности, то тогда вы столкнетесь с ошибкой ValueError.

Функции, используемые для управления генератором

random.seed(a=None, version=2)

С ее помощью мы запускаем работу генератора случайных чисел. Если a не указан или имеет значение None, то тогда системное время используется для генерации случайных значений. Если источники случайности предоставляются операционкой, то тогда системное время не используются, а применяются те, которые есть. 

При условии, что значение первого аргумента является целочисленным, оно применяется.

>>> random.seed(10)

>>> random.random()

0.5714025946899135

Второй параметр может иметь значения 1 и 2. По умолчанию используется 2. В этом случае объекты str, bytes, bytearray конвертируются в целочисленный тип, и все биты используются. Если же в качестве значения этого аргумента стоит единица, то тогда вырабатывается более узкий диапазон посева.

random.getstate()

С помощью этой функции мы можем получить объект, фиксирующий нынешнее состояние генератора случайных чисел. Данный объект может передаваться в setstate(), чтобы возобновить состояние.  

>>> random.getstate()

(3, (2910518045, 2919558713, 592432859, 1634426085,

....

2194693540, 2), None)




random.setstate(state)

state мы получаем из предыдущего метода. А этот восстанавливает внутреннее состояние генератора до такого, которое было получено при вызове прошлого метода.

random.getrandbits(k)

Возвращает целочисленное значение со случайными битами k. Этот метод поставляется вместе с генератором MersenneTwister, тогда как другие генераторы также могут его включать, но как необязательную часть API.

>>> random.getrandbits(8)

109

Также можно включать randrange(), чтобы обрабатывать не одно значение, а диапазон.

Некоторые другие функции генерации распределений

Появление функциональных параметров происходит после соответствующих переменных в уравнении распределения. Почти все эти уравнения находятся в статистических текстах. Приведем некоторые примеры функций.

random.random().

Эта функция возвращает случайное дробное число в пределах от 0 до 1. 

>>> random.random()

0.48256167455085586



random.uniform(a, b)

Этот метод позволяет получить случайное число с плавающей точкой N так, чтобы a <= N <= b для a <= b и b <= N <= a для b < a.

>>> random.uniform(2.5, 10.0)

2.611243345184153

Конечное значение b может как включаться в диапазон, так и нет. Все зависит от того, насколько было выполнено округление float в уравнении a + (b-a) * random().

random.triangular(low, high, mode)

Возвращает значение, сгенерированного генератором случайных чисел таким образом, что low <= N <= high и с указанным mode между этими границами. Границы low и high по умолчанию равны 0 и 1. 

>>> random.triangular(20, 60, 30)

34.605051874664895



random.expovariate(lambd)

Эта функция генерирует экспоненциальное распределение. В качестве аргумента используется единица, деленная на желаемое среднее значение. Важно – оно должно не быть равным нулю. а вот значение может возвращаться любое, начиная нулем и так до бесконечности. Но только в ряду положительных или отрицательных чисел в зависимости от того, какой знак числа, указанного в качестве аргумента.

ОфисГуру
Adblock
detector