Генерация псевдослучайных чисел — cppreference.com
Библиотека случайных чисел предоставляет классы, которые генерируют случайные и псевдослучайные числа. Эти классы включают:
- Равномерные генераторы случайных битов (URBG - Uniform random bit generators), которые включают в себя как генераторы случайных чисел, которые являются генераторами псевдослучайных чисел, генерирующие целочисленные последовательности с равномерным распределением, так и истинные генераторы случайных чисел, если они доступны;
- Распределения случайных чисел (например, равномерное, нормальное или распределение Пуассона) преобразуют выходные данные URBG в различные статистические распределения
URBG и распределения предназначены для совместного использования, чтобы получать случайные значения. Все генераторы случайных чисел могут быть специально инициализированы, сериализованы и десериализованы для использования с воспроизводимыми симуляторами.
Равномерные генераторы случайных битов
Равномерный генератор случайных битов это функциональный объект, возвращающий целые числа без знака, так что каждое значение в диапазоне возможных результатов имеет (в идеале) равную вероятность возврата.
Все равномерные генераторы случайных битов соответствуют требованиям UniformRandomBitGenerator.
C++20 также определяет концепт uniform_random_bit_generator.
Генераторы случайных чисел
Генераторы случайных чисел генерируют псевдослучайные числа, используя начальные данные в качестве источника энтропии. Несколько различных классов алгоритмов генерации псевдослучайных чисел реализованы в виде шаблонов, которые можно настраивать.
Выбор того, какой генератор использовать, связан с рядом компромиссов: линейный конгруэнтный генератор умеренно быстр и требует очень мало памяти для хранения состояния. Генераторы Фибоначчи с запаздыванием работают очень быстро даже на процессорах без расширенных наборов арифметических инструкций за счёт большего объема памяти, и иногда с менее желательными спектральными характеристиками. Твистер Мерсенна работает медленнее и имеет более высокие требования к хранению состояний, но при правильных параметрах имеет самую длинную неповторяющуюся последовательность с наиболее желательными спектральными характеристиками (желательных для данного определения).
Ни один из генераторов случайных чисел, предоставляемых стандартной библиотекой, не является криптографически безопасным, как и в случае любой безопасной операции, для этой цели следует использовать криптобиблиотеку (например, OpenSSL RAND_bytes).
Адаптеры генераторов случайных чисел
Адаптеры генераторов случайных чисел генерируют псевдослучайные числа с использованием других генераторов случайных чисел в качестве источника энтропии. Обычно они используются для изменения спектральных характеристик основного генератора.
Предопределённые генераторы случайных чисел
Предопределено несколько конкретных популярных алгоритмов.
Определены в заголовочном файле | |
| Тип | Определение |
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, 48271, 0, 2147483647>
Более новый "Минимальный стандарт", рекомендованный Парком, Миллером и Стокмейером в 1993 году[править] |
mt19937(C++11)
|
|
mt19937_64(C++11)
|
|
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>[править]
|
default_random_engine(C++11)
|
определяется реализацией |
Недетерминированные случайные числа
std::random_device это недетерминированный генератор равномерных случайных битов, хотя реализациям разрешено реализовывать std::random_device с использованием генератора псевдослучайных чисел, если нет поддержки не-детерминированной генерации случайных чисел.
| недетерминированный генератор случайных чисел с использованием аппаратного источника энтропии (класс) [править] |
Распределения случайных чисел
Распределение случайных чисел обрабатывает выходные данные URBG таким образом, чтобы полученные выходные данные распределялись в соответствии с определённой функцией статистической плотности вероятности.
Распределения случайных чисел соответствуют RandomNumberDistribution.
Определены в заголовочном файле | |
Равномерные распределения | |
(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) |
производит вещественные значения по F-распределению Фишера. (шаблон класса) [править] |
(C++11) |
производит вещественные значения по распределению Стьюдента. (шаблон класса) [править] |
Распределения выборки | |
(C++11) |
производит случайные целые числа по дискретному распределению (шаблон класса) [править] |
| выдаёт вещественные значения, распределённые по константным подынтервалам (шаблон класса) [править] | |
| выдаёт вещественные значения, распределяемые по определённым интервалам (шаблон класса) [править] | |
Утилиты
Определены в заголовочном файле | |
равномерно распределяет вещественные значения заданной точности по [0, 1) (шаблон функции) [править] | |
| универсальный генератор скремблированных исходных последовательностей с устранением смещения (класс) [править] | |
Библиотека случайных чисел C
В дополнение к генераторам и распределениям, описанным выше, также доступны функции и константы из библиотеки случайных чисел C, хотя это не рекомендуется:
Определены в заголовочном файле | |
| генерирует псевдослучайные числа (функция) [править] | |
| инициализирует псевдогенератор случайных чисел (функция) [править] | |
| максимально возможное значение, генерируемое std::rand (макроконстанта) [править] | |
Пример
#include <cmath> #include <iomanip> #include <iostream> #include <map> #include <random> #include <string> int main() { // Источник с реальным случайным значением, если доступно std::random_device r; // Выбираем случайное среднее от 1 до 6 std::default_random_engine e1(r()); std::uniform_int_distribution<int> uniform_dist(1, 6); int mean = uniform_dist(e1); std::cout << "Случайно выбранное среднее: " << mean << '\n'; // Генерируем нормальное распределение вокруг этого среднего 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 << "Нормальное распределение вокруг " << mean << ":\n" << std::fixed << std::setprecision(1); for (auto [x, y] : hist) std::cout << std::setw(2) << x << ' ' << std::string(y / 200, '*') << '\n'; }
Возможный вывод:
Случайно выбранное среднее: 4 Нормальное распределение вокруг 4: -4 -3 -2 -1 0 * 1 *** 2 ****** 3 ******** 4 ********* 5 ******** 6 ****** 7 *** 8 * 9 10 11 12