Модуль random для генерации случайных чисел
Случайные числа в программировании играют важную роль во многих процессах, например, при симуляции броска кости, генерации случайных входных данных или моделировании процессов.
Однако компьютер не способен создать по-настоящему случайное число, так как он является детерминированной системой, то есть при одних и тех же входных данных выдаёт один и тот же результат. Поэтому в программировании используются псевдослучайные числа, вычисляемые на основе начального значения, которое называют seed (с англ. – зерно).
Для работы с псевдослучайными числами в Python используется модуль random. Для использования функций из этого модуля его следует импортировать:
import random
По умолчанию модуль random использует текущее системное время как начальное значение. Поскольку время постоянно меняется, этого достаточно для большинства практических задач. Однако мы можем установить это начальное значение вручную с помощью функции random.seed():
random.seed(5)
Это полезно для отладки и воспроизводимости результатов, так как тогда генератор всегда будет выдавать одну и ту же последовательность псевдослучайных чисел.
Функции генерации чисел
Функции генерации чисел являются основой модуля random. Они создают базовые случайные значения, которые затем используются для всех остальных операций (выбора элементов, перемешивания и т.д.). Также они используют равномерное распределение, то есть каждое число в заданном диапазоне имеет равную вероятность быть выбранным.
|
Функция |
Описание |
Возвращаемое значение |
Диапазон |
|---|---|---|---|
|
|
Возвращает случайное число с плавающей точкой от 0 до 1, не включая 1 |
Число с плавающей точкой
|
[0.0, 1.0) |
|
|
Возвращает случайное число с плавающей точкой в диапазоне от |
[min, max] |
|
|
|
Возвращает случайное целое число из последовательности, которую можно создать с помощью функции |
Целое число
|
[ |
|
|
Возвращает случайное целое число в диапазоне от |
[min, max] |
Напомним, что в математике круглой скобкой обозначается открытый интервал (значение не включается), а квадратной – закрытый интервал (значение включается).
Генерация чисел с плавающей точкой
Случайные числа с плавающей точкой (float) генерируют функции random.random() и random.uniform().
Функция random.random() возвращает число, которое больше или равно 0, но строго меньше 1. Это может использоваться для работы с вероятностью, например, для создания события с вероятностью 1 %:
if random.random() <= 0.01:
print("Это легендарный персонаж!")
else:
print("Это дубина переговоров...")
Функция random.uniform() не ограничивает диапазон, из которого выбирается число, а позволяет задать его самостоятельно:
print(random.uniform(2, 2.5))
# Вывод: 2.0850676713833898
Причём обе границы min и max включаются в возможный результат.
Генерация целых чисел
Случайные целые числа (int) генерируют функции random.randrange() и random.randint().
Функция random.randrange() принимает те же параметры, что и функция range(): start, stop и step и возвращает случайное число из последовательности, которая могла бы быть создана функцией range() с этими параметрами:
print(random.randrange(2, 8, 2))
# Вывод: 2
Число start включается в возможный результат, а число stop – нет, поэтому здесь целое число выбирается из последовательности всех чётных чисел, больше или равных 2, но строго меньше 8.
Как и в функции range(), параметры start и step не являются обязательными, тогда число выбирается из последовательности от 0 до stop с шагом 1:
print(random.randrange(10))
# Вывод: 7
Вызов функции random.randint(a, b) эквивалентен вызову random.randrange(a, b + 1), то есть она возвращает случайное целое число из диапазона целых чисел от a до b включительно:
print(random.randint(1, 6))
# Вывод: 6
Функции для работы с последовательностями
Помимо генерации одиночных чисел, модуль random предоставляет функции для работы с последовательностями, то есть упорядоченными коллекциями. Они позволяют реализовать случайный выбор одного или нескольких элементов, а также изменение порядка элементов последовательности.
|
Функция |
Описание |
Возвращаемое значение |
|---|---|---|
|
|
Возвращает случайный элемент из последовательности |
Элемент последовательности |
|
|
Возвращает список длиной |
Список из |
|
|
Возвращает список длиной |
Список из |
|
|
Перемешивает элементы в последовательности |
|
Эти функции предназначены для работы со строками, кортежами и списками, однако строки и кортежи неизменяемы, поэтому в них нельзя перемешать символы с помощью функции random.shuffle(). Также модуль random не работает со множествами, так как они не упорядочены, и со словарями, так как к их элементам нельзя обратиться по индексу.
Выбор случайного элемента
Функция random.choice() возвращает один случайный элемент из непустой последовательности, которой может быть строка, список или кортеж:
print(random.choice(["Орёл", "Решка"]))
# Вывод: Орёл
Выбор нескольких случайных элементов
Выбрать несколько случайных элементов из последовательности позволяют функции random.sample() и random.choices(). Кроме последовательности seq они принимают целое число k – количество элементов, которые необходимо выбрать. Разница между этими двумя функциями заключается в том, что функция random.sample() не может выбрать один и тот же элемент повторно, поэтому число k не должно превышать длину последовательности seq, а функция random.choices() может выбрать один и тот же элемент несколько раз:
box = ["Белый шар", "Красный шар", "Чёрный шар"]
print(random.sample(box, 2))
# Вывод: ['Белый шар', 'Красный шар']
print(random.choices(box, k=5))
# Вывод: ['Красный шар', 'Чёрный шар', 'Чёрный шар', 'Чёрный шар', 'Белый шар']
При этом функция random.choices() принимает число k только как именованный аргумент, и по умолчанию он равен 1.
И если остальные рассмотренные функции модуля random выбирают элемент с равной вероятностью, то функция random.choices() позволяет изменить это с помощью параметра weights, в который можно передать список весов, определяющих вероятность выбора элемента.
Например, мы моделируем добычу ресурсов в игре. Пусть радужная руда является редким ресурсом и имеет базовый вес 1. С большей вероятностью (в 9 раз чаще) игрок добудет простую медную руду, поэтому её вес равен 9. То есть вероятность добычи радужной руды составляет 10%, а медной – 90%:
ore = ["Радужная руда", "Медная руда"]
print(random.choices(ore, weights=[1, 9], k=5))
# Вывод: ['Медная руда', 'Медная руда', 'Медная руда', 'Медная руда', 'Радужная руда']
Тогда при добыче руды (выборе 5 элементов из исходного списка) чаще всего будет добыта именно "Медная руда".
Перемешивание элементов
Функция random.shuffle() изменяет порядок элементов в последовательности, поэтому передаваемая ей последовательность должна быть изменяемым объектом, например, списком:
cards = ["Джокер", "Бубновый король", "Пиковый валет"]
random.shuffle(cards)
print(cards)
# Вывод: ['Бубновый король', 'Джокер', 'Пиковый валет']
Она изменяет исходный список и возвращает None.
Примеры
Пример 1. Моделирование броска двух игральных костей
Программа моделирует бросок двух игральных костей 10000 раз и подсчитывает, как часто выпадает сумма 7:
import random
target_count = 0
# Имитируем броски
for _ in range(10000):
roll1 = random.randint(1, 6)
roll2 = random.randint(1, 6)
current_sum = roll1 + roll2
if current_sum == 7:
target_count += 1
print(f"Сумма 7 выпала {target_count} раз за 10000 бросков")
print(f"Теоретическая вероятность: {6 / 36 * 100:.2f}%")
probability = (target_count / 10000) * 100
print(f"Экспериментальная вероятность: {probability:.2f}%")
Вывод:
Сумма 7 выпала 1680 раз за 10000 бросков
Теоретическая вероятность: 16.67%
Экспериментальная вероятность: 16.80%
Пример 2. Моделирование системы лутбоксов
Лутбоксом называют виртуальный предмет в игре, который содержит случайный набор игровых предметов, и у каждого предмета есть своя вероятность выпадения.
Программа моделирует получение предмета из лутбокса 1000 раз и подсчитывает, сколько раз выпал каждый предмет. Для этого используется класс Counter из встроенного модуля collections. Он предназначен для решения задачи подсчета неизменяемых объектов (например, строк или чисел) в коллекции, такой как список. Когда вы передаете список в Counter(), он возвращает словарь, где ключами являются уникальные элементы из списка (например, "Легендарный меч"), а значениями – количество раз, которое этот элемент встретился в списке:
import random
from collections import Counter # Встроенный класс для подсчета элементов
items = ["Легендарный меч", "Редкий лук", "Обычный щит", "Эликсир здоровья"]
# Веса как вероятности
weights = [0.5, 4.5, 15.0, 80.0]
# Выбираем N элементов с учетом заданных весов
results = random.choices(
population=items,
weights=weights,
k=1000
)
# Подсчитываем результаты с помощью Counter
drop_counts = Counter(results)
print(f"Лутбок открыт 1000 раз:")
for item, count in drop_counts.most_common():
# Вычисляем процент выпадения
percentage = (count / 1000) * 100
print(f"{item} получен {count} раз (вероятность {percentage:.2f}%)")
Вывод:
Лутбок открыт 1000 раз:
Эликсир здоровья получен 814 раз (вероятность 81.40%)
Обычный щит получен 137 раз (вероятность 13.70%)
Редкий лук получен 47 раз (вероятность 4.70%)
Легендарный меч получен 2 раз (вероятность 0.20%)
Пример 3. Генерация случайного аватара
Функция generate_avatar() генерирует случайный аватар, выбирая одну случайную часть тела из каждой категории (голова, тело, ноги):
import random
def generate_avatar() -> dict[str, str]:
"""Генерирует аватар, выбирая случайный элемент из каждой категории.
Возвращает:
Словарь с элементами аватара.
"""
avatar_parts = {
"Голова": ["Шлем викинга", "Ковбойская шляпа", "Кошачьи ушки"],
"Тело": ["Броня", "Спортивная майка", "Пижама"],
"Ноги": ["Ботинки", "Кроссовки", "Ласты"]
}
avatar_config = {}
for part_type, parts_list in avatar_parts.items():
# Выбираем один элемент из списка
selected_part = random.choice(parts_list)
avatar_config[part_type] = selected_part
return avatar_config
avatar1 = generate_avatar()
print("Аватар 1:")
for part, name in avatar1.items():
print(f"{part}: {name}")
avatar2 = generate_avatar()
print("\nАватар 2:")
for part, name in avatar2.items():
print(f"{part}: {name}")
Вывод:
Аватар 1:
Голова: Шлем викинга
Тело: Броня
Ноги: Кроссовки
Аватар 2:
Голова: Ковбойская шляпа
Тело: Спортивная майка
Ноги: Кроссовки
Итоги
- В программировании используются псевдослучайные числа, вычисляемые на основе начального значения.
- Модуль
randomпредоставляет функции для работы с псевдослучайными числами. - По умолчанию модуль
randomиспользует текущее системное время как начальное значение, но это можно изменить с помощью функцииrandom.seed(). - Случайное число с плавающей точкой от 0 до 1 возвращает функция
random(), а из заданного диапазона – функцияrandom.uniform(). - Случайное целое число из последовательности, создаваемой функцией
range()возвращает функцияrandrange(), а из заданного диапазона – функцияrandom.randint(). - Функция
random.choice()возвращает случайный элемент из последовательности, а функцияrandom.shuffle()перемешивает всю последовательность целиком. - Функции
random.sample()иrandom.choices()возвращают список заданной длины из последовательности, однако первая функция делает это без повторяющихся элементов, а вторая разрешает повторы.
Задания для самопроверки
1. Почему числа, генерируемые компьютером, называются псевдослучайными? Что такое seed, и для чего используется функция random.seed()?
Псевдослучайные числа не являются по-настоящему случайными числами и вычисляются на основе начального значения, которое называют seed. Установка начального значения с помощью функции random.seed() позволяет получать воспроизводимые результаты.
2. Напишите функцию random_temperature(min_temp, max_temp), которая принимает минимальное min_temp и максимальное max_temp значение температуры и возвращает случайную температуру (число с плавающей точкой) в этом диапазоне. Используя эту функцию, получите значение от 18.2℃ до 25.5℃ и выведите его на экран.
import random
def random_temperature(min_temp: int | float, max_temp: int | float) -> float:
return random.uniform(min_temp, max_temp)
temperature = random_temperature(18.2, 25)
print(temperature)
# Вывод: 24.619054246494198
3. Дан список участников телешоу participants = ["Анна", "Борис", "Светлана", "Дмитрий", "Елена"]. Перемешайте этот список и выведите его на экран до и после перемешивания.
import random
participants = ["Анна", "Борис", "Светлана", "Дмитрий", "Елена"]
initial_list = participants[:] # Копируем исходный список
random.shuffle(participants)
print(f"Список до перемешивания: {initial_list}")
# Вывод: ['Анна', 'Борис', 'Светлана', 'Дмитрий', 'Елена']
print(f"Список после перемешивания: {participants}")
# Вывод: ['Елена', 'Светлана', 'Борис', 'Дмитрий', 'Анна']
4. Дан список из четырех направлений света directions = ["Север", "Юг", "Восток", "Запад"]. Используйте одну из функций модуля random и выведите на экран случайное направление.
import random
directions = ["Север", "Юг", "Восток", "Запад"]
random_direction = random.choice(directions)
print(random_direction)
# Вывод: Север
5. Напишите функцию simulate_event(probability), которая которая принимает вероятность probability (в долях) и возвращает True с этой вероятностью и False в противном случае. В цикле for вызовите функцию simulate_event(0.2) 100 раз и подсчитайте, сколько раз было возвращено True (ожидается около 20). Результат выведите на экран.
import random
def simulate_event(probability: float) -> bool:
return random.random() < probability
for _ in range(100):
if simulate_event(0.2):
true_count += 1
print(true_count)
# 19
0 комментариев