Статьи

Математические модули в Python: случайные

Случайность вокруг нас. Когда вы подбрасываете монету или бросаете кубик, вы никогда не можете быть уверены в конечном результате. Эта непредсказуемость имеет множество применений, таких как определение победителей счастливого розыгрыша или генерация тестовых случаев для эксперимента со случайными значениями, полученными на основе алгоритма.

Помня об этой полезности, Python предоставил нам случайный модуль. Вы можете использовать его в играх для случайного появления врагов или для перемешивания элементов в списке.

Почти все функции в этом модуле зависят от базовой функции random() , которая будет генерировать случайное число с плавающей точкой, большее или равное нулю и меньше единицы. Python использует Mersenne Twister для генерации поплавков. Он производит 53-битные точности с периодом 2 ** 19937-1. На самом деле это наиболее широко используемый генератор псевдослучайных чисел общего назначения.

Иногда вы хотите, чтобы генератор случайных чисел воспроизводил последовательность чисел, созданную в первый раз. Это может быть достигнуто путем предоставления генераторам одинакового начального значения оба раза с использованием функции seed(s, version) . Если параметр s опущен, генератор будет использовать текущее системное время для генерации чисел. Вот пример:

1
2
3
4
5
6
7
8
9
import random
 
random.seed(100)
 
random.random()
# returns 0.1456692551041303
 
random.random()
# returns 0.45492700451402135

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

Модуль имеет две разные функции для генерации случайных целых чисел. Вы можете использовать randrange(a) для генерации случайного целого числа, меньшего, чем a .

Точно так же вы можете использовать randrange(a, b[,step]) для генерации случайного числа из range(a, b, step) . Например, использование random.randrange(0, 100, 3) вернет только те числа от 0 до 100, которые также делятся на 3.

Если вы знаете как нижний, так и верхний пределы, между которыми вы хотите генерировать числа, вы можете использовать более простую и интуитивно понятную функцию, называемую randint(a, b) . Это просто псевдоним для randrange(a, b+1) .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
import random
 
random.randrange(100)
# returns 65
 
random.randrange(100)
# returns 98
 
random.randrange(0, 100, 3)
# returns 33
 
random.randrange(0, 100, 3)
# returns 75
 
random.randint(1,6)
# returns 4
 
random.randint(1,6)
# returns 6

Чтобы выбрать случайный элемент из заданной непустой последовательности, вы можете использовать функцию choice(seq) . С randint() вы ограничены выбором чисел из данного диапазона. Функция choice(seq) позволяет вам выбрать число из любой последовательности, которую вы хотите.

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

Если вы хотите перетасовать последовательность вместо того, чтобы выбирать из нее случайный элемент, вы можете использовать функцию shuffle(seq) . Это приведет к перестановке последовательности на месте . Для последовательности, состоящей всего из 10 (n) элементов, может быть в общей сложности 3628800 (n!) Различных расположений. С большей последовательностью число возможных перестановок будет еще выше — это означает, что функция никогда не сможет генерировать все перестановки большой последовательности.

Допустим, вам нужно выбрать 50 студентов из группы из 100 студентов, чтобы отправиться в путешествие.

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

Лучшее решение — использовать функцию sample(seq, k) . Он вернет список из k уникальных элементов из данной последовательности. Исходная последовательность оставлена ​​без изменений. Элементы в результирующем списке будут в порядке выбора. Если k больше, чем количество элементов в самой последовательности, будет возникать ошибка ValueError .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import random
 
ids = [1, 8, 10, 12, 15, 17, 25]
 
random.choice(ids) # returns 8
random.choice(ids) # returns 15
 
names = [‘Tom’, ‘Harry’, ‘Andrew’, ‘Robert’]
 
random.choice(names) # returns Tom
random.choice(names) # returns Robert
 
random.shuffle(names)
names
# returns [‘Robert’, ‘Andrew’, ‘Tom’, ‘Harry’]
 
random.sample(names, 2)
# returns [‘Andrew’, ‘Robert’]
 
random.sample(names, 2)
# returns [‘Tom’, ‘Robert’]
 
names
# returns [‘Robert’, ‘Andrew’, ‘Tom’, ‘Harry’]

Как вы можете видеть, shuffle(seq) изменил исходный список, но sample(seq, k) сохранил его нетронутым.

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

Если вам просто нужно число от 0 до 1, вы можете использовать функцию random() . Если вы хотите, чтобы число находилось в определенном диапазоне, вы можете использовать uniform(a, b) с a и b в качестве нижнего и верхнего пределов соответственно.

Допустим, вам нужно сгенерировать случайное число между низким и высоким таким, чтобы оно имело большую вероятность нахождения вблизи другого режима чисел. Вы можете сделать это с помощью triangular(low, high, mode) функции. Низкие и высокие значения будут 0 и 1 по умолчанию. Аналогично, значение режима по умолчанию соответствует средней точке низкого и высокого значения, что приводит к симметричному распределению.

Существует также множество других функций для генерации случайных чисел на основе различных распределений. Например, вы можете использовать normalvariate(mu, sigma) чтобы сгенерировать случайное число на основе нормального распределения с mu как среднее значение и sigma как стандартное отклонение.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
import random
 
random.random()
# returns 0.8053547502449923
 
random.random()
# returns 0.05966180559620815
 
random.uniform(1, 20)
# returns 11.970525425108205
 
random.uniform(1, 20)
# returns 7.731292430291898
 
random.triangular(1, 100, 80)
# returns 42.328674062298816
 
random.triangular(1, 100, 80)
# returns 73.54693076132074

Как мы только что видели, можно генерировать случайные числа с равномерным распределением, а также с треугольным или нормальным распределением. Даже в конечном диапазоне, например, от 0 до 100, существует бесконечное число операций с плавающей запятой. Что, если существует конечный набор элементов, и вы хотите добавить больший вес к некоторым конкретным значениям при выборе случайного числа? Такая ситуация распространена в лотерейных системах, где числам с небольшим вознаграждением присваивается высокий вес.

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

1
2
3
4
5
6
7
import random
 
w_prizes = [(‘$1’, 300), (‘$2’, 50), (‘$10’, 5), (‘$100’, 1)]
prize_list = [prize for prize, weight in w_prizes for i in range(weight)]
 
random.choice(prize_list)
# returns ‘$1’

В моем случае потребовалось десять испытаний, чтобы получить приз в 2 доллара, выбранный из списка. Шансы на получение приза в 100 долларов будут намного ниже. Точно так же вы также можете добавить смещение для других таких программ.

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

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