Генерация случайного числа в диапазоне на С++
Чтобы получить случайное число в С++ используется функция rand() из модуля <cstdlib> . Она генерирует псевдослучайные целые числа в диапазоне от нуля до константы RAND_MAX , значение которой зависит от компилятора (стандартом языка не регламентируется).
Числа псевдослучайные, значит используется некий алгоритм генерации, это может бычть что угодно, например линейный конгруэнтный датчик — стандарт также не фиксирует этот вопрос. Важно, что все такие алгоритмы используют «затравку», то есть некоторое первое число, с которого начинается генерация. Если мы не зададим это число — то будет использоваться скорее всего ноль, а при каждом запуске программы мы будем получать одинаковые случайные числа. Задавать эту константу заранее известным значением удобно, например, для тестирования программы. Однако, если мы хотим чтобы значения были каждый раз новые — нужно использоваться функцию srand(int) , которая задает значение затравки.
В приведенной программе генерируется случайное число, при этом значение затравки задается с помощью функции time , которая возвращает текущее время. Прочитать про нее можно тут: Замерить время работы функции на С++.
Чтобы сгенерировать число в диапазоне от 0 до to , можно использовать деление по модулю:
Генерация в диапазоне от from до to — это тоже самое, что генерация от нуля до to-from , но к результату надо добавить to:
При этом, необходимо, чтобы from был меньше to .
Про функции rand, srand и одинаковые случайные числа
Немного исследуем функцию rand, для этого напишем такой пример:
Сколько бы мы ее не запускали — будем получать одинаковый результат. Но почему? Давайте разбираться вместе. Загляним внутрь одной из возможных реализаций этой функции:
Функция возвращает целые числа (от 0 до 32767). Не вдаваясь в подробности этого кода, полученное случайное число, зависит от стартового числа next , которое, как вы видите, установлено в единицу. Отсюда и следует, что числа всегда получаются одинаковыми. Для того, чтобы избежать этой проблемы, в паре с rand() нужно использовать функцию srand( ). Вот ее внутренности:
Как видите, эта функция изменяет стартовое число next , присваивая ему другую величину, получаемую функцией в качестве аргумента. В принципе, это число можно вводить каждый раз вручную, например, так:
В этом случае, вводя разные значения переменной seed , мы будем получать различные случайные величины на выходе. Чаще всего в качестве передаваемой величины в функцию srand() используют системное время в секундах, а задание затравки вручную исопльзуется только в отладочных целях.
Рандомное число в промежутке A и B
Написал программу в которой пользователь может задать числа А и В.
А — минимальное число.
В — максимальное число.
Т.е. по факту это промежуток чисел,тут же программа должна вывести Х — случайное число из данного промежутка.
Проблема в том, что компиляторы(пробовал на онлайн и CodeBlocks) выдают либо одно и тоже число, либо вообще превышают максимальное число — В .
Я же вводил А = 10,В = 100,получал при каждом повторе — Х = 93,бывало и больше 100. В чём проблема? P.s. оставлю 2 кода
![]()
![]()
С приходом стандарта C++11 появился заголовочный файл <random> , позволяющий явно генерировать случайное число из закрытого интервала, причём с равномерным распределением. Используется для этого шаблонный класс std::uniform_int_distribution.
При этом вы получаете значения в диапазоне [a,b) .
Если надо до b включительно ( [a,b] )-
При каждом программы запуске rand() выдает одну и ту же последовательность случайных чисел. Можете однократно вызвать в начале программы srand(time(0)) — для инициализации ГСЧ значением текущего времени.
![]()
Случайные числа в языке программирования С++ могут быть сгенерированы функцией rand() из стандартной библиотеки С++. Функция rand() генерирует числа в диапазоне от 0 до RAND_MAX . RAND_MAX — это константа, определённая в библиотеке <cstdlib> . Для MVS RAND_MAX = 32767, но оно может быть и больше, в зависимости от компилятора. Ниже показана простая программка, использующая генератор случайных чисел rand() :
Для того чтобы масштабировать интервал генерации чисел нужно воспользоваться, операцией нахождения остатка от деления % .
В вашем случае это будет:
![]()
Всё ещё ищете ответ? Посмотрите другие вопросы с метками c++ математика случайные-числа или задайте свой вопрос.
Site design / logo © 2022 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2022.6.10.42345
Нажимая «Принять все файлы cookie», вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
<random>
Определяет средства для генерации случайных чисел с равномерным распределением.
Требования
Заголовок: <random>
Пространство имен: std
Библиотека <random> использует оператор «#include <initializer_list>».
Сводка
Генератор случайных чисел — это объект, формирующий последовательность из псевдослучайных чисел. Генератор, который выдает значения с равномерным распределением в указанном диапазоне, называют равномерным генератором случайных чисел (РГСЧ). Шаблон класса, предназначенный для работы в качестве URNG, называется обработчиком , если этот класс имеет определенные общие признаки, которые рассматриваются далее в этой статье. РГСЧ может объединяться и обычно объединяется с распределением путем передачи РГСЧ в качестве аргумента в operator() распределения для получения значений, распределенных в соответствии с заданным распределением.
Эти ссылки ведут к основным разделам статьи.
Краткие советы
Вот несколько советов по использованию <random> .
В большинстве случаев РГСЧ формируют необработанные значения, которые упорядочиваются распределением. (Заметное исключение из этого заключается в std::shuffle() том, что он использует URNG напрямую.)
Один экземпляр РГСЧ или распределения не может безопасно вызываться параллельно, так как использование РГСЧ или распределения — это операция изменения. Дополнительные сведения см. в разделе Потоковая безопасность в стандартной библиотеке C++.
Предлагаются предварительно заданные определения типов для нескольких механизмов. Это рекомендуемый способ создания РГСЧ при использовании механизма.
Самое полезное сочетание для большинства приложений — это механизм mt19937 с uniform_int_distribution , как показано в примере кода далее в этой статье.
В заголовке можно выбрать различные варианты <random> ; любой из них предпочтительнее устаревшей функции библиотеки времени выполнения C rand() . Для информации о недостатках rand() и о том, как <random> работает с этими недостатками, см. это видео.
Примеры
В следующем примере кода показана генерация случайных чисел; в этом случае пять из них используют генератор, созданный с недетерминистическим начальным значением.
Это высококачественные случайные числа, они разные при каждом запуске этой программы, но не обязательно находятся в полезном диапазоне. Для управления диапазоном следует использовать однородное распределение, как показано в следующем коде:
В следующем примере кода показан более реалистичный набор случаев использования с однородно распределенными генераторами случайных чисел, перемешивающих содержимое векторов и массивов.
Этот код показывает два разных метода рандомизации (вектора целых чисел и перемешивания массива индексированных данных) с помощью тестовой функции шаблона. В первом вызове тестовой функции используется криптобезопасный, недетерминистический, неповторяющийся РГСЧ random_device без начального значения. Во втором вызове в качестве РГСЧ используется mersenne_twister_engine с детерминистическим 32-разрядным постоянным начальным значением; это означает, что результаты повторяются. В третьем вызове для mersenne_twister_engine используется 32-разрядное недетерминистическое значение — результат выполнения random_device . В четвертом вызове применяется последовательность начальных значений, заполненная результатами выполнения random_device , что обеспечивает рандомизацию лучше, чем 32-разрядный недетерминистический подход (но все еще не обеспечивает криптобезопасность). Чтобы узнать больше, читайте дальше.
Классифицированные списки
Равномерные генераторы случайных чисел
РГСЧ часто описываются следующими свойствами.
Длина периода: число итераций до повторения последовательности чисел. Чем период длиннее, тем лучше.
Производительность: сколько времени и памяти требуется для получения чисел. Чем меньше, тем лучше.
Качество: насколько полученная последовательность близка к реальным случайным числам. Часто это называется «стохастичностью«.
В следующих разделах перечислены РГСЧ, доступные в заголовке <random> .
Недетерминистический генератор
random_device Класса
Формирует недетерминистическую, криптографическую безопасную случайную последовательность с помощью внешнего устройства. Обычно используется для получения начального значения для механизма случайных чисел. Низкая производительность, очень высокое качество. Дополнительные сведения см. в примечаниях.
Определения типа механизма с предварительно заданными параметрами
Для инициации механизмов и адаптеров. Дополнительные сведения см. в разделе Механизмы и распределения.
default_random_engine Механизм по умолчанию.
knuth_b Механизм Кнута.
minstd_rand0 Минимальный стандартный механизм 1988 (Льюис, Гудмэн и Миллер [Lewis, Goodman, and Miller], 1969).
minstd_rand Обновленный минимальный стандартный механизм minstd_rand0 (Парк, Миллер и Стокмайер [Park, Miller, and Stockmeyer], 1993).
mt19937 32-разрядный механизм типа «Вихрь Мерсенна» (Матсумото и Нишимура [Matsumoto and Nishimura], 1998).
mt19937_64 64-разрядный механизм типа «Вихрь Мерсенна» (Матсумото и Нишимура [Matsumoto and Nishimura], 2000).
ranlux24 24-разрядный механизм RANLUX (Мартин Люшер и Фред Джеймс [Martin Lüscher and Fred James], 1994).
ranlux24_base Используется в качестве основания для ranlux24 .
ranlux48 48-разрядный механизм RANLUX (Мартин Люшер и Фред Джеймс [Martin Lüscher and Fred James], 1994).
ranlux48_base Используется в качестве основания для ranlux48 .
Шаблоны механизмов
Шаблоны механизмов используются как автономные РГСЧ или как базовые механизмы, которые передаются адаптерам механизмов. Обычно они создаются с предварительно заданным определением типа механизма и передаются в распределение. Дополнительные сведения см. в разделе Механизмы и распределения.
| Имя | Описание |
|---|---|
| linear_congruential_engine Класса | Создает случайную последовательность, используя линейный конгруэнтный алгоритм. Самый простой с самым низким качеством. |
| mersenne_twister_engine Класса | Создает случайную последовательность, используя алгоритм «Вихрь Мерсенна». Самый сложный с самым высоким качеством (кроме класса random_device). Очень высокая производительность. |
| subtract_with_carry_engine Класса | Создает случайную последовательность, используя алгоритм вычитания с переносом. Улучшение linear_congruential_engine , но с более низким качеством и производительностью, чем у mersenne_twister_engine . |
Шаблоны адаптеров механизмов
Адаптеры механизмов — это шаблоны, адаптирующие другие (базовые) механизмы. Обычно они создаются с предварительно заданным определением типа механизма и передаются в распределение. Дополнительные сведения см. в разделе Механизмы и распределения.
| Имя | Описание |
|---|---|
| discard_block_engine Класса | Создает случайную последовательность, удаляя значения, возвращенные базовым механизмом. |
| independent_bits_engine Класса | Создает случайную последовательность с указанным числом разрядов, перемешивая разряды из значений, возвращенных базовым механизмом. |
| shuffle_order_engine Класса | Создает случайную последовательность, изменяя порядок значений, возвращенных базовым механизмом. |
Распределения случайных чисел
В следующих разделах перечислены распределения, доступные в заголовке <random> . Распределения — это механизмы постобработки, которые обычно используют результаты РГСЧ в качестве входа и распределяют выходные данные с помощью заданной функции плотности статистической вероятности. Дополнительные сведения см. в разделе Механизмы и распределения.
Равномерные распределения
| Имя | Описание |
|---|---|
| uniform_int_distribution Класса | Создает равномерное целочисленное распределение значений по диапазону в закрытом интервале [a, b] (инклюзивное инклюзивное). |
| uniform_real_distribution Класса | Формирует равномерное распределение вещественных чисел (с плавающей запятой) в диапазоне, заданном полузамкнутым интервалом [a, b) (a включено, b не входит в диапазон). |
| generate_canonical | Формирует равномерное распределение вещественных чисел (с плавающей запятой) с заданной точностью в диапазоне [0, 1) (0 входит в диапазон, 1 не входит). |
Распределения Бернулли
| Имя | Описание |
|---|---|
| bernoulli_distribution Класса | Формирует распределение Бернулли значений типа bool . |
| binomial_distribution Класса | Формирует биномиальное распределение целых значений. |
| geometric_distribution Класса | Формирует геометрическое распределение целых значений. |
| negative_binomial_distribution Класса | Формирует отрицательное биномиальное распределение целых значений. |
Нормальные распределения
| Имя | Описание |
|---|---|
| cauchy_distribution Класса | Формирует распределение Коши вещественных значений (с плавающей запятой). |
| chi_squared_distribution Класса | Формирует распределение хи-квадрат вещественных значений (с плавающей запятой). |
| fisher_f_distribution Класса | Создает F-распределение (также известное как распределение F Snedecor или распределение Fisher-Snedecor) реальных (с плавающей запятой). |
| lognormal_distribution Класса | Формирует логарифмически нормальное распределение вещественных значений (с плавающей запятой). |
| normal_distribution Класса | Формирует нормальное (Гауссово) распределение вещественных значений (с плавающей запятой). |
| student_t_distribution Класса | Формирует t-распределение Стьюдента вещественных значений (с плавающей запятой). |
Распределения Пуассона
| Имя | Описание |
|---|---|
| exponential_distribution Класса | Формирует экспоненциальное распределение вещественных значений (с плавающей запятой). |
| extreme_value_distribution Класса | Формирует распределение экстремальных вещественных значений (с плавающей запятой). |
| gamma_distribution Класса | Формирует гамма-распределение вещественных значений (с плавающей запятой). |
| poisson_distribution Класса | Формирует распределение Пуассона целых значений. |
| weibull_distribution Класса | Формирует распределение Вейбулла вещественных значений (с плавающей запятой). |
Выборочные распределения
| Имя | Описание |
|---|---|
| discrete_distribution Класса | Формирует дискретное распределение целых чисел. |
| piecewise_constant_distribution Класса | Формирует кусочно-постоянное распределение вещественных значений (с плавающей запятой). |
| piecewise_linear_distribution Класса | Формирует кусочно-линейное распределение вещественных значений (с плавающей запятой). |
Служебные функции
В этом разделе перечислены основные служебные функции, доступные в заголовке <random> .
| Имя | Описание |
|---|---|
| seed_seq Класса | Создает шифрованную порождающую последовательность без смещения. Используется для предотвращения повтора потоков случайных чисел. Полезно, если на основе механизмов инициализируется множество РГСЧ. |
Операторы
В этом разделе перечислены операторы, доступные в заголовке <random> .
| Имя | Описание |
|---|---|
| operator== | Проверка на то, что РГСЧ с левой стороны оператора равен механизму с правой стороны. |
| operator!= | Проверка на то, что РГСЧ с левой стороны оператора не равен механизму с правой стороны. |
| operator<< | Запись сведений о состоянии в поток. |
| operator>> | Извлечение сведений о состоянии из потока. |
Механизмы и распределения
Сведения о каждой из категорий шаблонов классов, определенных в следующих разделах, см. в <random> следующих разделах. Обе эти категории шаблонов классов принимают тип в качестве аргумента и используют общие имена параметров шаблона для описания свойств типа, разрешенного как фактический тип аргумента, следующим образом:
IntType обозначает short , int , long , long long , unsigned short , unsigned int , unsigned long или unsigned long long .
UIntType обозначает unsigned short , unsigned int , unsigned long или unsigned long long .
RealType обозначает float , double или long double .
Двигатели
Шаблоны механизмов и шаблоны адаптеров механизмов — это шаблоны, параметры которых настраивают созданный генератор.
Обработчик — это шаблон класса или класса, экземпляры которого (генераторы) служат источником случайных чисел, равномерно распределенных между минимальным и максимальным значением. Адаптер механизма предоставляет последовательность значений с различной стохастичностью, беря значения, сформированные другим механизмом случайных чисел, и применяя к ним определенный алгоритм.
Каждый механизм и адаптер механизма содержат следующие члены.
typedef numeric-type result_type — это тип, возвращаемый operator() генератора. numeric-type передается как параметр шаблона при создании экземпляра.
result_type operator() возвращает значения, которые равномерно распределены между min() и max() .
result_type min() возвращает минимальное значение, полученное от функции operator() генератора. Адаптеры механизма используют результат функции min() базового механизма.
result_type max() возвращает максимальное значение, полученное от функции operator() генератора. Если result_type — это целочисленный тип, то max() — это максимальное значение, которое может быть возвращено (инклюзивное). Если result_type — это вещественное значение, то max() — это наименьшее значение, превышающее все значения, которые могут быть возвращены (неинклюзивное). Адаптеры механизма используют результат функции max() базового механизма.
void seed(result_type s) задает для генератора начальное значение s . Для механизмов используется сигнатура void seed(result_type s = default_seed) для поддержки параметров по умолчанию (в адаптерах механизмов определена отдельная функция void seed() , как показано далее).
template <class Seq> void seed(Seq& q) семена генератора с помощью . seed_seq Seq
Явный конструктор с аргументом result_type x , который создает генератор, начальное значение которого определяется так же, как при вызове функции seed(x) .
Явный конструктор с аргументом seed_seq& seq , который создает генератор, начальное значение которого определяется так же, как при вызове функции seed(seq) .
void discard(unsigned long long count) вызывает функцию operator() count раз и удаляет каждое значение.
Адаптеры механизмов также поддерживают следующие члены ( Engine — это первый параметр шаблона адаптера механизма, обозначающий тип базового механизма):
Конструктор по умолчанию, который инициализирует генератор так же, как конструктор базового механизма по умолчанию.
Явный конструктор с аргументом const Engine& eng . Это необходимо для поддержки конструкции копирования с использованием базового механизма.
Явный конструктор с аргументом Engine&& eng . Это необходимо для поддержки конструкции перемещения с использованием базового механизма.
void seed() инициализирует генератор с использованием начального значения базового механизма по умолчанию.
Функция свойства const Engine& base() возвращает базовый механизм, который использовался для создания генератора.
Каждый механизм поддерживает состояние, определяющее последовательность значений, которые будут созданы последующими вызовами operator() . Состояние двух генераторов, созданных на основе механизмов одного типа, можно сравнить с помощью операторов operator== и operator!= . Если два состояния равны, генераторы будут получать одинаковые последовательности значений. Состояние объекта можно сохранить в поток как последовательность 32-разрядных беззнаковых значений, используя оператор operator<< генератора. Состояние после сохранения не изменяется. Сохраненное состояние можно считать в генератор, созданный на основе механизма того же типа, используя оператор operator>> .
Дистрибутивы
Распределение случайных чисел — это шаблон класса или класса, экземпляры которого преобразуют поток равномерно распределенных случайных чисел, полученных от обработчика, в поток случайных чисел, имеющих определенное распределение. У каждого распределения есть следующие члены.
typedef numeric-type result_type — это тип, возвращаемый функцией operator() распределения. numeric-type передается как параметр шаблона при создании экземпляра.
template <class URNG> result_type operator()(URNG& gen) возвращает значения, которые распределяются в соответствии с определением распределения, используя gen в качестве источника равномерно распределенных случайных значений и сохраненные параметры распределения.
template <class URNG> result_type operator()(URNG& gen, param_type p) возвращает значения, которые распределены в соответствии с определением распределения, используя gen в качестве источника случайных значений с равномерным распределением и структуру параметров p .
typedef unspecified-type param_type — это пакет параметров, которые могут передаваться функции operator() и использоваться вместо сохраненных параметров для формирования возвращаемого значения.
Конструктор const param& инициализирует сохраненные параметры на основе своего аргумента.
param_type param() const получает сохраненные параметры.
void param(const param_type&) задает сохраненные параметры на основе своего аргумента.
result_type min() возвращает минимальное значение, полученное от функции operator() распределения.
result_type max() возвращает максимальное значение, полученное от функции operator() распределения. Если result_type — это целочисленный тип, то max() — это максимальное значение, которое может быть возвращено (инклюзивное). Если result_type — это вещественное значение, то max() — это наименьшее значение, превышающее все значения, которые могут быть возвращены (неинклюзивное).
void reset() удаляет любые кэшированные значения, чтобы результат следующего вызова operator() не зависел от любых значений, полученных от механизма перед вызовом.
Структура параметров — это объект, в котором хранятся все параметры, необходимые для распределения. Она содержит следующие виртуальные машины:
typedef distribution-type distribution_type , тип распределения.
Один или несколько конструкторов, которые принимают такие же наборы параметров, что и конструкторы распределения.
Такие же функции параметров и доступа, как у распределения.
Операторы сравнения равенства и неравенства.
Дополнительные сведения см. ниже в справочных подразделах, указанных ранее в этой статье.
Комментарии
В Visual Studio есть два очень полезных РГСЧ — mt19937 и random_device , которые показаны в следующей таблице.
| РГСЧ | быстрый; | Криптобезопасный | С начальным значением | Детерминированный |
|---|---|---|---|---|
| mt19937 | Да | Нет | Да | Да * |
| random_device | Нет | Да | Нет | Нет |
* Если предоставлено известное начальное значение.
Хотя согласно стандарту ISO для C++ функция random_device не обязана быть криптографически безопасной, в Visual Studio она реализована как криптобезопасная. (Термин «криптографически безопасный» не подразумевает гарантии, но относится к минимальному уровню энтропии ( и, следовательно, уровню прогнозируемости) предоставляет данный алгоритм случайности. Дополнительные сведения см. в статье Википедии о криптографически защищенном генераторе псевдорандомных чисел.) Так как стандарт ISO C++ не требует этого, другие платформы могут реализовать random_device как простой генератор псевдослучайных чисел (не криптографически защищенный) и может быть подходит только в качестве источника начального значения для другого генератора. При использовании random_device в коде для разных платформ изучите документацию по этим платформам.
По определению, результаты random_device не воспроизводятся повторно; это значит, что эта функция может работать значительно медленнее, чем другие РГСЧ. Большинство приложений, которые не должны быть криптобезопасными, используют mt19937 или аналогичный механизм, хотя для заполнения начального значения можно вызвать random_device , как показано в примере кода.