Генерация псевдослучайных чисел
Библиотека генерации случайных чисел предоставляет классы для генерации случайных и псевдослучайных чисел. К ним относятся:
- Равномерные генераторы случайных битов (URBG), включая движки случайных чисел — генераторы псевдослучайных чисел, создающие целочисленные последовательности с равномерным распределением, — и генераторы истинно случайных чисел (если доступны).
- Распределения случайных чисел (например, равномерное, нормальное или распределение Пуассона), преобразующие выходные данные URBG в различные статистические распределения.
URBG и распределения предназначены для совместного использования при получении случайных значений. Все движки случайных чисел можно явно инициализировать начальными данными, сериализовать и десериализовать для использования в воспроизводимых симуляторах.
Равномерные генераторы случайных битов
Равномерный генератор случайных битов — это функциональный объект, возвращающий беззнаковые целочисленные значения, причём каждое значение из диапазона возможных результатов (в идеале) имеет одинаковую вероятность возврата.
Все равномерные генераторы случайных битов соответствуют требованиям UniformRandomBitGenerator. В C++20 также определено понятие uniform_random_bit_generator.
Определён в заголовочном файле <random> |
|
|---|---|
|
(C++20) | указывает, что тип соответствует требованиям равномерного генератора случайных битов (понятие) |
Движки случайных чисел
Движок случайных чисел (обычно сокращённо движок ) — это равномерный генератор случайных битов, создающий псевдослучайные числа с использованием начальных данных в качестве источника энтропии.
В любой момент времени движок e типа E имеет состояние ei для некоторого неотрицательного целого числа i. При создании e имеет начальное состояние e0, определяемое параметрами движка и начальным значением (или последовательностью начальных значений).
Для любого типа движка E всегда определены следующие свойства:
- Размер состояния
Eв единицах размераE::result_type(то есть(sizeof ei) / sizeof(E::result_type)). - Алгоритм перехода
TA, с помощью которого состояниеeeiпереходит в следующее состояниеei+1(то естьTA(ei) == ei+1). - Алгоритм генерации
GA, с помощью которого состояниеeотображается в значение типаE::result_type; результатом является псевдослучайное число.
Последовательность псевдослучайных чисел можно сгенерировать, попеременно вызывая TA и GA.
Стандартная библиотека предоставляет реализации трёх различных классов алгоритмов генерации псевдослучайных чисел в виде шаблонов классов, что позволяет настраивать алгоритмы. Выбор движка связан с рядом компромиссов:
- Линейный конгруэнтный движок работает с умеренной скоростью и требует очень мало памяти для хранения состояния.
- Движок вихря Мерсенна работает медленнее и требует больше памяти для хранения состояния, но при правильном выборе параметров обеспечивает самую длинную неповторяющуюся последовательность с наиболее желательными спектральными характеристиками (при заданном определении желательных характеристик).
- Движок вычитания с заёмом работает очень быстро даже на процессорах без расширенных наборов арифметических инструкций, но требует больше памяти для хранения состояния и иногда обладает менее желательными спектральными характеристиками.
| (начиная с C++26) |
Ни один из этих движков случайных чисел не является криптографически стойким. Как и для любой защищённой операции, для этих целей следует использовать криптографическую библиотеку (например, OpenSSL RAND_bytes).
Все типы, созданные на основе этих шаблонов, соответствуют требованиям RandomNumberEngine.
Определён в заголовочном файле <random> |
|
|---|---|
|
(C++11) | реализует алгоритм линейного конгруэнтного генератора (шаблон класса) |
|
(C++11) | реализует алгоритм вихря Мерсенна (шаблон класса) |
|
(C++11) | реализует алгоритм вычитания с заёмом (генератор Фибоначчи с запаздыванием) (шаблон класса) |
|
(C++26) | параллелизуемый генератор на основе счётчика (шаблон класса) |
Адаптеры движков случайных чисел
Адаптеры движков случайных чисел генерируют псевдослучайные числа, используя другой движок случайных чисел в качестве источника энтропии. Обычно они применяются для изменения спектральных характеристик базового движка.
Определён в заголовочном файле <random> |
|
|---|---|
|
(C++11) | отбрасывает часть выходных данных движка случайных чисел (шаблон класса) |
|
(C++11) | упаковывает выходные данные движка случайных чисел в блоки заданного числа битов (шаблон класса) |
|
(C++11) | выдаёт выходные данные движка случайных чисел в ином порядке (шаблон класса) |
Предопределённые генераторы случайных чисел
Предопределено несколько популярных алгоритмов.
Определён в заголовочном файле <random> |
|
|---|---|
| Тип | Определение |
minstd_rand0 (C++11) |
std::linear_congruential_engine<std::uint_fast32_t, 16807,0,2147483647> Открыт в 1969 году Льюисом, Гудманом и Миллером; принят как «минимальный стандарт» в 1988 году Парком и Миллером |
minstd_rand (C++11) | std::linear_congruential_engine<std::uint_fast32_t, |
mt19937 (C++11) | std::mersenne_twister_engine<std::uint_fast32_t, |
mt19937_64 (C++11) | std::mersenne_twister_engine<std::uint_fast64_t, |
ranlux24_base (C++11) | std::subtract_with_carry_engine<std::uint_fast32_t,24,10,24> |
ranlux48_base (C++11) | std::subtract_with_carry_engine<std::uint_fast64_t,48,5,12> |
ranlux24 (C++11) |
std::discard_block_engine<std::ranlux24_base,223,23> 24-разрядный генератор RANLUX, созданный Мартином Люшером и Фредом Джеймсом в 1994 году |
ranlux48 (C++11) |
std::discard_block_engine<std::ranlux48_base,389,11> 48-разрядный генератор RANLUX, созданный Мартином Люшером и Фредом Джеймсом в 1994 году |
knuth_b (C++11) | std::shuffle_order_engine<std::minstd_rand0,256> |
philox4x32 (C++26) |
std::philox_engine<std::uint_fast32_t,32,4,10, 0xCD9E8D57,0x9E3779B9, 0xD2511F53,0xBB67AE85> |
philox4x64 (C++26) |
std::philox_engine<std::uint_fast64_t,64,4,10, 0xCA5A826395121157,0x9E3779B97F4A7C15, 0xD2E7470EE14C6C93,0xBB67AE8584CAA73B> |
default_random_engine (C++11) | тип RandomNumberEngine, определяемый реализацией |
Недетерминированные случайные числа
std::random_device — это недетерминированный равномерный генератор случайных битов, хотя реализациям разрешено реализовывать std::random_device с помощью движка псевдослучайных чисел, если поддержка генерации недетерминированных случайных чисел отсутствует.
|
(C++11) | недетерминированный генератор случайных чисел, использующий аппаратный источник энтропии (класс) |
Распределения случайных чисел
Распределение случайных чисел выполняет постобработку выходных данных URBG таким образом, чтобы результирующие данные соответствовали заданной статистической функции плотности вероятности.
Распределения случайных чисел соответствуют требованиям RandomNumberDistribution.
Определён в заголовочном файле <random> |
|
|---|---|
Равномерные распределения |
|
|
(C++11) | генерирует целочисленные значения, равномерно распределённые в диапазоне (шаблон класса) |
|
(C++11) | генерирует вещественные значения, равномерно распределённые в диапазоне (шаблон класса) |
Распределения Бернулли |
|
|
(C++11) | генерирует значения bool в соответствии с распределением Бернулли (класс) |
|
(C++11) | генерирует целочисленные значения в соответствии с биномиальным распределением (шаблон класса) |
|
(C++11) | генерирует целочисленные значения в соответствии с отрицательным биномиальным распределением (шаблон класса) |
|
(C++11) | генерирует целочисленные значения в соответствии с геометрическим распределением (шаблон класса) |
Распределения Пуассона |
|
|
(C++11) | генерирует целочисленные значения в соответствии с распределением Пуассона (шаблон класса) |
|
(C++11) | генерирует вещественные значения в соответствии с экспоненциальным распределением (шаблон класса) |
|
(C++11) | генерирует вещественные значения в соответствии с гамма-распределением (шаблон класса) |
|
(C++11) | генерирует вещественные значения в соответствии с распределением Вейбулла (шаблон класса) |
|
(C++11) | генерирует вещественные значения в соответствии с распределением экстремальных значений (шаблон класса) |
Нормальные распределения |
|
|
(C++11) | генерирует вещественные значения в соответствии со стандартным нормальным (гауссовым) распределением (шаблон класса) |
|
(C++11) | генерирует вещественные значения в соответствии с логнормальным распределением (шаблон класса) |
|
(C++11) | генерирует вещественные значения в соответствии с распределением хи-квадрат (шаблон класса) |
|
(C++11) | генерирует вещественные значения в соответствии с распределением Коши (шаблон класса) |
|
(C++11) | генерирует вещественные значения в соответствии с F-распределением Фишера (шаблон класса) |
|
(C++11) | генерирует вещественные значения в соответствии с t-распределением Стьюдента (шаблон класса) |
Распределения выборки |
|
|
(C++11) | генерирует целочисленные значения в соответствии с дискретным распределением (шаблон класса) |
|
(C++11) | генерирует вещественные значения, распределённые по заданным постоянным подынтервалам (шаблон класса) |
|
(C++11) | генерирует вещественные значения, распределённые по заданным подынтервалам линейно (шаблон класса) |
Утилиты
Определён в заголовочном файле <random> |
|
|---|---|
|
(C++11) | равномерно распределяет вещественные значения заданной точности по диапазону [0, 1) (шаблон функции) |
|
(C++11) | универсальный генератор перемешанной последовательности начальных значений, устраняющий смещение (класс) |
Алгоритмы генерации случайных чисел
Определён в заголовке <random> |
|
|---|---|
|
(C++26) | заполняет диапазон случайными числами из равномерного генератора случайных битов (функциональный объект алгоритма) |
Библиотека случайных чисел C
Помимо описанных выше генераторов и распределений, доступны также функции и константы из библиотеки случайных чисел C, хотя их использование не рекомендуется:
Определён в заголовке <cstdlib> |
|
|---|---|
| генерирует псевдослучайное число (функция) |
|
| инициализирует генератор псевдослучайных чисел (функция) |
|
максимальное возможное значение, генерируемое std::rand (макроконстанта) |
|
Пример
#include <cmath>
#include <iomanip>
#include <iostream>
#include <map>
#include <random>
#include <string>
int main()
{
// Seed with a real random value, if available
std::random_device r;
// Choose a random mean between 1 and 6
std::default_random_engine e1(r());
std::uniform_int_distribution<int> uniform_dist(1, 6);
int mean = uniform_dist(e1);
std::cout << "Randomly-chosen mean: " << mean << '\n';
// Generate a normal distribution around that mean
std::seed_seq seed2{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 e2(seed2);
std::normal_distribution<> normal_dist(mean, 2);
std::map<int, int> hist;
for (int n = 0; n != 10000; ++n)
++hist[std::round(normal_dist(e2))];
std::cout << "Normal distribution around " << mean << ":\n"
<< std::fixed << std::setprecision(1);
for (auto [x, y] : hist)
std::cout << std::setw(2) << x << ' ' << std::string(y / 200, '*') << '\n';
}
Возможный вывод:
Randomly-chosen mean: 4 Normal distribution around 4: -4 -3 -2 -1 0 * 1 *** 2 ****** 3 ******** 4 ********* 5 ******** 6 ****** 7 *** 8 * 9 10 11 12
См. также
| Документация C по теме Генерация псевдослучайных чисел |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/numeric/random