Я уверен, что в какой-то момент мы все использовали 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> есть много других движков и дистрибутивов. Если вам интересно, посмотрите документацию здесь.