1. Введение в псевдослучайные числа: инициализация, seed и базовая функция random
Введение в псевдослучайные числа: инициализация, seed и базовая функция random
Добро пожаловать в курс «Полное руководство по модулю random в Python». Мы начинаем наше путешествие с самых основ. Прежде чем мы научимся генерировать случайные пароли, перемешивать колоды карт или моделировать сложные вероятностные процессы, нам нужно понять, как компьютер — машина, работающая по строгим правилам логики, — вообще способен создавать что-то «случайное».
В этой статье мы разберем концепцию псевдослучайности, познакомимся с генератором Вихрь Мерсенна, научимся управлять хаосом с помощью зерна (seed) и изучим фундамент всего модуля — функцию random().
Парадокс случайности в детерминированном мире
Компьютеры детерминированы. Это означает, что если вы дадите компьютеру одни и те же входные данные и попросите выполнить одну и ту же программу, он всегда выдаст одинаковый результат. всегда равно . Это свойство делает компьютеры надежными, но создает огромную проблему, когда нам нужна непредсказуемость.
Истинная случайность (True Randomness) в природе существует — например, распад радиоактивного атома или атмосферный шум. Но для обычного процессора создание случайного числа — это невыполнимая задача без внешнего оборудования.
Поэтому программисты используют псевдослучайные числа (Pseudo-Random Numbers). Это последовательности чисел, которые выглядят случайными и проходят статистические тесты на случайность, но на самом деле генерируются с помощью строгого математического алгоритма.
Как работают генераторы псевдослучайных чисел (PRNG)
Генератор псевдослучайных чисел (PRNG — Pseudo-Random Number Generator) — это алгоритм, который начинает с исходного числа (называемого seed или зерно) и производит последовательность чисел, используя математические операции.
Чтобы понять принцип, рассмотрим простейший пример алгоритма — Линейный конгруэнтный метод. Хотя Python использует более сложный алгоритм, этот пример идеально подходит для понимания сути процесса.
Формула генерации следующего числа выглядит так:
Где:
Суть проста: мы берем число, умножаем его, прибавляем другое число, делим и берем остаток. Полученный результат становится входным данным для следующего шага. Если мы знаем начальное число () и коэффициенты, мы можем предсказать всю последовательность наперед.
Вихрь Мерсенна (Mersenne Twister)
Модуль random в Python использует алгоритм под названием Вихрь Мерсенна (Mersenne Twister), а именно его версию MT19937.
Его ключевые особенности:
Однако важно помнить: Вихрь Мерсенна не является криптографически стойким. Это значит, что если злоумышленник соберет достаточное количество сгенерированных чисел, он сможет вычислить внутреннее состояние генератора и предсказать все будущие числа.
> Никогда не используйте модуль random для генерации паролей, токенов безопасности или ключей шифрования. Для этих целей в Python существует модуль secrets.
Базовая функция: random.random()
Теперь перейдем к практике. Основой всего модуля является функция random(). Почти все остальные функции модуля (генерация целых чисел, выбор элемента из списка и т.д.) внутри себя используют random().
Импорт и использование
Функция random.random() возвращает случайное число с плавающей точкой (float) в диапазоне .
Обратите внимание на скобки в математической записи диапазона:
[ означает, что включено в диапазон.) означает, что исключено из диапазона.То есть, теоретически вы можете получить 0.0, но никогда не получите ровно 1.0 (максимальное значение будет очень близко к единице, например, 0.999999...).
Зачем нам число от 0 до 1?
Может показаться, что число от 0 до 1 не очень полезно, если вам нужно бросить кубик (1-6). Однако, имея число в этом диапазоне, мы можем легко масштабировать его до любого другого интервала.
Например, если мы хотим получить число от 0 до 100:
Где:
random.random() (от 0 до 1).В Python это выглядело бы так:
Управление хаосом: random.seed()
Мы выяснили, что псевдослучайные числа генерируются на основе формул. Это приводит нас к важному инструменту — инициализации генератора, или seeding.
Функция random.seed(a=None) инициализирует генератор случайных чисел.
Автоматическая инициализация
Если вы не вызываете seed() явно, Python делает это за вас при первом импорте модуля. В качестве зерна (начального значения) обычно используется текущее системное время. Поскольку время постоянно меняется, при каждом запуске программы вы получаете разные последовательности чисел.
Ручная инициализация (Воспроизводимость)
Иногда нам нужно, чтобы «случайная» последовательность была одинаковой при каждом запуске программы. Это критически важно для:
Если мы передадим в seed() конкретное число (или строку, или байты), генератор перейдет в определенное состояние и будет выдавать одну и ту же последовательность.
![Иллюстрация принципа детерминизма при использовании одинакового seed: разные машины выдают одинаковый результат.
Рассмотрим пример:
Результат выполнения этого кода будет примерно таким:
Как видите, последовательности идентичны. Число 42 здесь выбрано произвольно, это может быть любое целое число, строка или байтовый объект. Главное — оно должно быть неизменным.
Локальный и глобальный Random
Важно понимать, что функции random.random(), random.seed() и другие, которые мы вызываем напрямую из модуля, используют один общий глобальный экземпляр генератора Random.
Если вы пишете большую программу с множеством потоков или модулей, изменение seed в одном месте повлияет на генерацию случайных чисел во всей программе. В продвинутых сценариях (о которых мы поговорим в будущих статьях) лучше создавать изолированные экземпляры класса random.Random.
Резюме
* Компьютеры используют псевдослучайные числа (PRNG), которые генерируются детерминированными алгоритмами.
* Python использует алгоритм Вихрь Мерсенна (Mersenne Twister).
* Функция random.random() возвращает float в диапазоне .
* Функция random.seed() позволяет зафиксировать начальное состояние генератора, обеспечивая воспроизводимость результатов.
* Модуль random не подходит для криптографии. Для паролей используйте модуль secrets.
В следующей статье мы отойдем от теории и начнем работать с целыми числами, изучая функции randint, randrange и их особенности.