<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-разрядный недетерминистический подход (но все еще не обеспечивает криптобезопасность). Чтобы узнать больше, читайте дальше.
Списки по категориям
Универсальные генераторы случайных чисел
РГСЧ часто описываются следующими свойствами.
Длина периода: число итераций до повторения последовательности чисел. Чем период длиннее, тем лучше.
Производительность: сколько времени и памяти требуется для получения чисел. Чем меньше, тем лучше.
Качество: насколько полученная последовательность близка к реальным случайным числам. Часто это называется "стохастичностью".
В следующих разделах перечислены РГСЧ, доступные в заголовке <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
.
Подсистемы
Шаблоны механизмов и шаблоны адаптеров механизмов — это шаблоны, параметры которых настраивают созданный генератор.
Обработчик — это шаблон класса или класса, экземпляры которого (генераторы) являются источником случайных чисел, равномерно распределенных между минимальным и максимальным значением. Адаптер механизма предоставляет последовательность значений с различной стохастичностью, беря значения, сформированные другим механизмом случайных чисел, и применяя к ним определенный алгоритм.
Каждый механизм и адаптер механизма содержат следующие члены.
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 |
Да | No | Да | Yes* |
random_device |
No | Да | No | No |
* Если предоставлено известное начальное значение.
Хотя согласно стандарту ISO для C++ функция random_device
не обязана быть криптографически безопасной, в Visual Studio она реализована как криптобезопасная. (Термин "криптографически безопасный" не подразумевает гарантии, но относится к минимальному уровню энтропии ( и, следовательно, уровню прогнозируемости — заданному алгоритму случайности). Дополнительные сведения см. в статье Википедии о криптографически защищенном генераторе псевдорандомных чисел.) Так как стандарт ISO C++ не требует этого, другие платформы могут реализовать random_device
как простой генератор псевдо-случайных чисел (не криптографически безопасный) и может быть подходит только в качестве источника начального значения для другого генератора. При использовании random_device
в коде для разных платформ изучите документацию по этим платформам.
По определению, результаты random_device
не воспроизводятся повторно; это значит, что эта функция может работать значительно медленнее, чем другие РГСЧ. Большинство приложений, которые не должны быть криптобезопасными, используют mt19937
или аналогичный механизм, хотя для заполнения начального значения можно вызвать random_device
, как показано в примере кода.