<random>

Определяет средства для генерации случайных чисел с равномерным распределением.

Требования

Заголовок: <random>

Пространство имен: std

Примечание.

Библиотека <random> использует инструкцию #include <initializer_list>.

Итоги

Генератор случайных чисел — это объект, формирующий последовательность из псевдослучайных чисел. Генератор, который выдает значения с равномерным распределением в указанном диапазоне, называют равномерным генератором случайных чисел (РГСЧ). Шаблон класса, предназначенный для работы в качестве URNG, называется обработчиком, если этот класс имеет определенные общие признаки, которые рассматриваются далее в этой статье. РГСЧ может объединяться и обычно объединяется с распределением путем передачи РГСЧ в качестве аргумента в operator() распределения для получения значений, распределенных в соответствии с заданным распределением.

Эти ссылки ведут к основным разделам статьи.

Краткие советы

Вот несколько советов по использованию <random>.

  • В большинстве случаев РГСЧ формируют необработанные значения, которые упорядочиваются распределением. (Важное исключение из этого заключается в std::shuffle() том, что он использует URNG напрямую.)

  • Один экземпляр РГСЧ или распределения не может безопасно вызываться параллельно, так как использование РГСЧ или распределения — это операция изменения. Дополнительные сведения см. в разделе Потоковая безопасность в стандартной библиотеке C++.

  • Предлагаются предварительно заданные определения типов для нескольких механизмов. Это рекомендуемый способ создания РГСЧ при использовании механизма.

  • Самое полезное сочетание для большинства приложений — это механизм mt19937 с uniform_int_distribution, как показано в примере кода далее в этой статье.

В заголовке можно выбрать различные варианты <random>; любой из них предпочтительнее устаревшей функции библиотеки времени выполнения C rand(). Для информации о недостатках rand() и о том, как <random> работает с этими недостатками, см. это видео.

Примеры

В следующем примере кода показана генерация случайных чисел; в этом случае пять из них используют генератор, созданный с недетерминистическим начальным значением.

#include <random>
#include <iostream>

using namespace std;

int main()
{
    random_device rd;   // non-deterministic generator
    mt19937 gen(rd());  // to seed mersenne twister.
                        // replace the call to rd() with a
                        // constant value to get repeatable
                        // results.

    for (int i = 0; i < 5; ++i) {
        cout << gen() << " "; // print the raw output of the generator.
    }
    cout << endl;
}
2430338871 3531691818 2723770500 3252414483 3632920437

Это высококачественные случайные числа, они разные при каждом запуске этой программы, но не обязательно находятся в полезном диапазоне. Для управления диапазоном следует использовать однородное распределение, как показано в следующем коде:

#include <random>
#include <iostream>

using namespace std;

int main()
{
    random_device rd;   // non-deterministic generator
    mt19937 gen(rd());  // to seed mersenne twister.
    uniform_int_distribution<> dist(1,6); // distribute results between 1 and 6 inclusive.

    for (int i = 0; i < 5; ++i) {
        cout << dist(gen) << " "; // pass the generator to the distribution.
    }
    cout << endl;
}
5 1 6 1 2

В следующем примере кода показан более реалистичный набор случаев использования с однородно распределенными генераторами случайных чисел, перемешивающих содержимое векторов и массивов.

// cl.exe /EHsc /nologo /W4 /MTd
#include <algorithm>
#include <array>
#include <iostream>
#include <random>
#include <string>
#include <vector>
#include <functional> // ref()

using namespace std;

template <typename C> void print(const C& c) {
    for (const auto& e : c) {
        cout << e << " ";
    }

    cout << endl;
}

template <class URNG>
void test(URNG& urng) {

    // Uniform distribution used with a vector
    // Distribution is [-5, 5] inclusive
    uniform_int_distribution<int> dist(-5, 5);
    vector<int> v;

    for (int i = 0; i < 20; ++i) {
        v.push_back(dist(urng));
    }

    cout << "Randomized vector: ";
    print(v);

    // Shuffle an array
    // (Notice that shuffle() takes a URNG, not a distribution)
    array<string, 26> arr = { { "H", "He", "Li", "Be", "B", "C", "N", "O", "F",
        "Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc",
        "Ti", "V", "Cr", "Mn", "Fe" } };

    shuffle(arr.begin(), arr.end(), urng);

    cout << "Randomized array: ";
    print(arr);
    cout << "--" << endl;
}

int main()
{
    // First run: non-seedable, non-deterministic URNG random_device
    // Slower but crypto-secure and non-repeatable.
    random_device rd;
    cout << "Using random_device URNG:" << endl;
    test(rd);

    // Second run: simple integer seed, repeatable results
    cout << "Using constant-seed mersenne twister URNG:" << endl;
    mt19937 engine1(12345);
    test(engine1);

    // Third run: random_device as a seed, different each run
    // (Desirable for most purposes)
    cout << "Using non-deterministic-seed mersenne twister URNG:" << endl;
    mt19937 engine2(rd());
    test(engine2);

    // Fourth run: "warm-up" sequence as a seed, different each run
    // (Advanced uses, allows more than 32 bits of randomness)
    cout << "Using non-deterministic-seed \"warm-up\" sequence mersenne twister URNG:" << endl;
    array<unsigned int, mt19937::state_size> seed_data;
    generate_n(seed_data.begin(), seed_data.size(), ref(rd));
    seed_seq seq(begin(seed_data), end(seed_data));
    mt19937 engine3(seq);
    test(engine3);
}
Using random_device URNG:
Randomized vector: 5 -4 2 3 0 5 -2 0 4 2 -1 2 -4 -3 1 4 4 1 2 -2
Randomized array: O Li V K C Ti N Mg Ne Sc Cl B Cr Mn Ca Al F P Na Be Si Ar Fe S He H
--
Using constant-seed mersenne twister URNG:
Randomized vector: 3 -1 -5 0 0 5 3 -4 -3 -4 1 -3 0 -3 -2 -4 5 1 -1 -1
Randomized array: Al O Ne Si Na Be C N Cr Mn H V F Sc Mg Fe K Ca S Ti B P Ar Cl Li He
--
Using non-deterministic-seed mersenne twister URNG:
Randomized vector: 5 -4 0 2 1 -2 4 4 -4 0 0 4 -5 4 -5 -1 -3 0 0 3
Randomized array: Si Fe Al Ar Na P B Sc H F Mg Li C Ti He N Mn Be O Ca Cr V K Ne Cl S
--
Using non-deterministic-seed "warm-up" sequence mersenne twister URNG:
Randomized vector: -1 3 -2 4 1 3 0 -5 5 -5 0 0 5 0 -3 3 -4 2 5 0
Randomized array: Si C Sc H Na O S Cr K Li Al Ti Cl B Mn He Fe Ne Be Ar V P Ca N Mg F
--

Этот код показывает два разных метода рандомизации (вектора целых чисел и перемешивания массива индексированных данных) с помощью тестовой функции шаблона. В первом вызове тестовой функции используется криптобезопасный, недетерминистический, неповторяющийся РГСЧ random_device без начального значения. Во втором вызове в качестве РГСЧ используется mersenne_twister_engine с детерминистическим 32-разрядным постоянным начальным значением; это означает, что результаты повторяются. В третьем вызове для mersenne_twister_engine используется 32-разрядное недетерминистическое значение — результат выполнения random_device. В четвертом вызове применяется последовательность начальных значений, заполненная результатами выполнения random_device, что обеспечивает рандомизацию лучше, чем 32-разрядный недетерминистический подход (но все еще не обеспечивает криптобезопасность). Чтобы узнать больше, читайте дальше.

Списки по категориям

Универсальные генераторы случайных чисел

РГСЧ часто описываются следующими свойствами.

  1. Длина периода: число итераций до повторения последовательности чисел. Чем период длиннее, тем лучше.

  2. Производительность: сколько времени и памяти требуется для получения чисел. Чем меньше, тем лучше.

  3. Качество: насколько полученная последовательность близка к реальным случайным числам. Часто это называется "стохастичностью".

В следующих разделах перечислены РГСЧ, доступные в заголовке <random>.

Недетерминированный генератор

random_device Класса
Формирует недетерминистическую, криптографическую безопасную случайную последовательность с помощью внешнего устройства. Обычно используется для получения начального значения для механизма случайных чисел. Низкая производительность, очень высокое качество. Дополнительные сведения см. в разделе Замечания.

Типды ядра с предопределенными параметрами

Для инициации механизмов и адаптеров. Дополнительные сведения см. в разделе Механизмы и распределения.

  • default_random_engineМеханизм по умолчанию.

    typedef mt19937 default_random_engine;
    
  • knuth_b Механизм Кнута.

    typedef shuffle_order_engine<minstd_rand0, 256> knuth_b;
    
  • minstd_rand0 Минимальный стандартный механизм 1988 (Льюис, Гудмэн и Миллер [Lewis, Goodman, and Miller], 1969).

    typedef linear_congruential_engine<unsigned int, 16807, 0, 2147483647> minstd_rand0;
    
  • minstd_rand Обновленный минимальный стандартный механизм minstd_rand0 (Парк, Миллер и Стокмайер [Park, Miller, and Stockmeyer], 1993).

    typedef linear_congruential_engine<unsigned int, 48271, 0, 2147483647> minstd_rand;
    
  • mt19937 32-разрядный механизм типа "Вихрь Мерсенна" (Матсумото и Нишимура [Matsumoto and Nishimura], 1998).

    typedef mersenne_twister_engine<
        unsigned int, 32, 624, 397,
        31, 0x9908b0df,
        11, 0xffffffff,
        7, 0x9d2c5680,
        15, 0xefc60000,
        18, 1812433253> mt19937;
    
  • mt19937_64 64-разрядный механизм типа "Вихрь Мерсенна" (Матсумото и Нишимура [Matsumoto and Nishimura], 2000).

    typedef mersenne_twister_engine<
        unsigned long long, 64, 312, 156,
        31, 0xb5026f5aa96619e9ULL,
        29, 0x5555555555555555ULL,
        17, 0x71d67fffeda60000ULL,
        37, 0xfff7eee000000000ULL,
        43, 6364136223846793005ULL> mt19937_64;
    
  • ranlux24 24-разрядный механизм RANLUX (Мартин Люшер и Фред Джеймс [Martin Lüscher and Fred James], 1994).

    typedef discard_block_engine<ranlux24_base, 223, 23> ranlux24;
    
  • ranlux24_base Используется в качестве основания для ranlux24.

    typedef subtract_with_carry_engine<unsigned int, 24, 10, 24> ranlux24_base;
    
  • ranlux48 48-разрядный механизм RANLUX (Мартин Люшер и Фред Джеймс [Martin Lüscher and Fred James], 1994).

    typedef discard_block_engine<ranlux48_base, 389, 11> ranlux48;
    
  • ranlux48_base Используется в качестве основания для ranlux48.

    typedef subtract_with_carry_engine<unsigned long long, 48, 5, 12> ranlux48_base;
    

Шаблоны подсистемы

Шаблоны механизмов используются как автономные РГСЧ или как базовые механизмы, которые передаются адаптерам механизмов. Обычно они создаются с предварительно заданным определением типа механизма и передаются в распределение. Дополнительные сведения см. в разделе Механизмы и распределения.

Имя Описание
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 (также известное как распределение Snedecor F или распределение Фишер-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.

Подсистемы

Шаблоны механизмов и шаблоны адаптеров механизмов — это шаблоны, параметры которых настраивают созданный генератор.

Обработчик — это шаблон класса или класса, экземпляры которого (генераторы) являются источником случайных чисел, равномерно распределенных между минимальным и максимальным значением. Адаптер механизма предоставляет последовательность значений с различной стохастичностью, беря значения, сформированные другим механизмом случайных чисел, и применяя к ним определенный алгоритм.

Каждый механизм и адаптер механизма содержат следующие члены.

  • typedefnumeric-typeresult_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_seqSeq.

  • Явный конструктор с аргументом 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>>.

Дистрибутивы

Распределение случайных чисел — это шаблон класса или класса, экземпляры которого преобразуют поток равномерно распределенных случайных чисел, полученных от подсистемы в поток случайных чисел с определенным распределением. У каждого распределения есть следующие члены.

  • typedefnumeric-typeresult_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.

  • typedefunspecified-typeparam_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() не зависел от любых значений, полученных от механизма перед вызовом.

Структура параметров — это объект, в котором хранятся все параметры, необходимые для распределения. Она содержит:

  • typedefdistribution-typedistribution_type, тип распределения.

  • Один или несколько конструкторов, которые принимают такие же наборы параметров, что и конструкторы распределения.

  • Такие же функции параметров и доступа, как у распределения.

  • Операторы сравнения равенства и неравенства.

Дополнительные сведения см. ниже в справочных подразделах, указанных ранее в этой статье.

Замечания

В Visual Studio есть два очень полезных РГСЧ — mt19937 и random_device, которые показаны в следующей таблице.

РГСЧ Быстро Криптобезопасный С начальным значением Детерминированное
mt19937 Да Нет Да Yes*
random_device Нет Да No No

* Если предоставлено известное начальное значение.

Хотя согласно стандарту ISO для C++ функция random_device не обязана быть криптографически безопасной, в Visual Studio она реализована как криптобезопасная. (Термин "криптографически безопасный" не подразумевает гарантии, но относится к минимальному уровню энтропии ( и, следовательно, уровню прогнозируемости — заданному алгоритму случайности). Дополнительные сведения см. в статье Википедии о криптографически защищенном генераторе псевдорандомных чисел.) Так как стандарт ISO C++ не требует этого, другие платформы могут реализовать random_device как простой генератор псевдо-случайных чисел (не криптографически безопасный) и может быть подходит только в качестве источника начального значения для другого генератора. При использовании random_device в коде для разных платформ изучите документацию по этим платформам.

По определению, результаты random_device не воспроизводятся повторно; это значит, что эта функция может работать значительно медленнее, чем другие РГСЧ. Большинство приложений, которые не должны быть криптобезопасными, используют mt19937 или аналогичный механизм, хотя для заполнения начального значения можно вызвать random_device, как показано в примере кода.

См. также

Справочник по файлам заголовков