Как приручить рандом?
Рандомайзеры кажутся простой вещью — ведь в любом языке программирования есть встроенные генераторы случайных чисел. Например, в C# можно использовать класс Random. Но важно понимать: это не «настоящая случайность», а псевдослучайность — числа получаются по алгоритму и при одинаковом начальном значении (seed) последовательность будет одинаковой.
Эмиль Габриелян, .NET-разработчик Altenar, рассказал, как правильно использовать генераторы случайных чисел и что выбрать для разных задач.
Как работает Random
Класс Random в .NET основан на генерации псевдослучайной последовательности из начального числа (seed). По умолчанию seed берётся из системного времени.
Отсюда две особенности.
- Если создавать несколько объектов Random подряд слишком быстро, они могут инициализироваться одинаковым seed и давать одинаковые числа.
- Если использовать один экземпляр долго, последовательность будет достаточно разнообразной для большинства бытовых задач (игры, симуляции, выбор случайных элементов).
С выходом .NET 6 появилась удобная альтернатива — Random.Shared. Это готовый потокобезопасный экземпляр, который можно использовать в любом месте без риска получить одинаковые последовательности:
Где нужна настоящая непредсказуемость
Если требуется безопасность (генерация паролей, токенов, криптографических ключей), Random не подходит. Его последовательность можно воспроизвести, если знать seed.
Для таких случаев есть криптографически стойкий генератор — System.Security.Cryptography.RandomNumberGenerator. Он использует энтропию операционной системы:
Когда стоит фиксировать seed
Иногда предсказуемость полезна. В модульных тестах или при симуляциях для отладки удобно, чтобы при каждом запуске программа выдавала одну и ту же «случайную» последовательность. Для этого можно явно задать seed:
Настоящая энтропия
Операционная система собирает хаотичные события (движения мыши, время между нажатиями клавиш, сетевые задержки). Эти данные доступны через такие источники, как /dev/random и /dev/urandom в Linux. Именно они лежат в основе криптографических генераторов, которые мы используем через .NET API.
«Просто рандома» не бывает. Важно понимать задачу и уметь выбирать подходящий инструмент. Для игр, симуляций и выборки данных достаточно Random (инициализированного один раз). Для всего, что связано с безопасностью, используйте только криптографические генераторы (RandomNumberGenerator). Для тестирования задавайте фиксированный seed. Если понимать природу псевдослучайности, то можно ей управлять и получать именно ту «случайность», которая нужна.
Хотите услышать больше историй об IT? Если да, то подписывайтесь на наш основной блог в Telegram, чтобы получить больше опыта от экспертов из Altenar.
#экспертиза@altenar_b2b