Я уверен, что в какой-то момент мы все использовали rand()
для генерации случайных чисел. Если вы используете C, у вас не так много выбора, но если вы используете C ++ 11 (или выше), вы упускаете его.
В C ++ 11 добавлен замечательный заголовок <random>
, который дает вам новые способы генерации случайных чисел. Сначала это немного сложнее, чем просто позвонить rand()
, но оно того стоит. Код легче читать, есть много других вариантов, и вы получите правильное распределение случайных чисел. Эта статья познакомит вас с основами.
Если у вас мало времени и вам нужен только пример кода, прокрутите вниз. Если вам нужно краткое объяснение того, как работает <random>
, продолжайте читать!
Двигатели
Механизмы случайных чисел - это просто разные алгоритмы генерации случайных чисел, которые берут начальное число и генерируют псевдослучайные числа. Они позволяют выполнять множество настроек, которые для обычного программного проекта вам не нужно беспокоить. Вот для чего нужны генераторы случайных чисел, описанные ниже.
Генераторы
Как я уже сказал выше, движки случайных чисел имеют множество настроек и могут быть довольно сложными. Генераторы случайных чисел - это предварительно сконфигурированные механизмы случайных чисел, которые позволяют быстро и легко приступить к работе.
Вы, вероятно, будете использовать mt19937
, алгоритм Мерсенна Твистера. Этот алгоритм имеет хорошее соотношение эффективности и случайности и, вероятно, подойдет для 99% проектов. Если вы решите копнуть глубже и узнать больше о других двигателях / генераторах и конфигурации, вы, вероятно, знаете, что делаете.
mt19937
(и несколько других генераторов / алгоритмов) необходимо засеять. Для этого мы используем движок random_device
. Этот движок извлекает случайные данные из вашей операционной системы и оборудования. Это то, что мы используем как семя.
Распределения
Следующая часть - это распределения случайных чисел. Они принимают выходные данные двигателя и распределяют их, чтобы преобразовать их в нужные вам значения. Обычно вы используете uniform_int_distribution
или uniform_real_distribution
в зависимости от того, хотите ли вы целое или действительное число. Также есть bernoulli_distribution
для логических значений.
Пример
Вот простой пример: сгенерируйте целое число от 1 до 10 включительно (включение означает, что оно включает пределы; поэтому возможные числа будут 1, 2, 3, 4, 5, 6, 7, 8, 9 и 10).
Мы создаем наш random_device
, используем его для заполнения mt19937
, затем создаем распределение, передавая минимум (1) и максимум (10) в конструктор. Наконец, чтобы получить число, мы используем dist(mt)
, передавая его в наш механизм случайных чисел.
Что, если бы мы хотели получить значения с плавающей запятой? Пример почти идентичен, за исключением того, что мы используем uniform_real_distribution
, что даст нам любое действительное число.
Если вы когда-либо выполняете отладку и хотите каждый раз генерировать одни и те же числа, вы всегда можете заменить rd()
в конструкторе mt
на постоянное значение, чтобы дать ему постоянное начальное число.
Наконец, логические. И снова пример практически идентичен, за исключением того, что мы используем bernoulli_distribution
:
Источники и дополнительная информация
Поздравляем, теперь вы можете перестать использовать rand()
! Этот пост был вдохновлен докладом Стефана Т. Лававея rand () Считается вредным. Если у вас есть полчаса и вы хотите узнать больше о том, почему вам следует использовать rand()
и многое другое о генерации случайных чисел в C ++, зацените это здесь.
Я говорил только о самом минимуме того, что большинству людей понадобится при нормальной разработке программного обеспечения, но у <random>
есть много других движков и дистрибутивов. Если вам интересно, посмотрите документацию здесь.