Генерация псевдослучайных чисел
Библиотека случайных чисел предоставляет классы, которые генерируют случайные и псевдослучайные числа. Эти классы включают:
- Равномерные генераторы случайных битов (URBG - Uniform random bit generators), которые включают в себя как генераторы случайных чисел, которые являются генераторами псевдослучайных чисел, генерирующие целочисленные последовательности с равномерным распределением, так и истинные генераторы случайных чисел, если они доступны;
- Распределения случайных чисел (например, равномерное, нормальное или распределение Пуассона) преобразуют выходные данные URBG в различные статистические распределения
URBG и распределения предназначены для совместного использования, чтобы получать случайные значения. Все генераторы случайных чисел могут быть специально инициализированы, сериализованы и десериализованы для использования с воспроизводимыми симуляторами.
Равномерные генераторы случайных битов
Равномерный генератор случайных битов это функциональный объект, возвращающий целые числа без знака, так что каждое значение в диапазоне возможных результатов имеет (в идеале) равную вероятность возврата.
Все равномерные генераторы случайных битов соответствуют требованиям UniformRandomBitGenerator.
C++20 также определяет концепт uniform_random_bit_generator.
Определены в заголовочном файле
<random> | |
(C++20) |
указывает, что тип квалифицируется как однородный генератор случайных битов (концепт) |
Генераторы случайных чисел
Генераторы случайных чисел генерируют псевдослучайные числа, используя начальные данные в качестве источника энтропии. Несколько различных классов алгоритмов генерации псевдослучайных чисел реализованы в виде шаблонов, которые можно настраивать.
Выбор того, какой генератор использовать, связан с рядом компромиссов: линейный конгруэнтный генератор умеренно быстр и требует очень мало памяти для хранения состояния. Генераторы Фибоначчи с запаздыванием работают очень быстро даже на процессорах без расширенных наборов арифметических инструкций за счёт большего объема памяти, и иногда с менее желательными спектральными характеристиками. Твистер Мерсенна работает медленнее и имеет более высокие требования к хранению состояний, но при правильных параметрах имеет самую длинную неповторяющуюся последовательность с наиболее желательными спектральными характеристиками (желательных для данного определения).
Ни один из генераторов случайных чисел, предоставляемых стандартной библиотекой, не является криптографически безопасным, как и в случае любой безопасной операции, для этой цели следует использовать криптобиблиотеку (например, OpenSSL RAND_bytes).
Определены в заголовочном файле
<random> | |
(C++11) |
реализует линейный конгруэнтный алгоритм (шаблон класса) |
(C++11) |
реализует алгоритм Мерсен Твистер (шаблон класса) |
(C++11) |
реализует алгоритм вычитания с переносом (Фибоначчи с запаздыванием) (шаблон класса) |
Адаптеры генераторов случайных чисел
Адаптеры генераторов случайных чисел генерируют псевдослучайные числа с использованием других генераторов случайных чисел в качестве источника энтропии. Обычно они используются для изменения спектральных характеристик основного генератора.
Определены в заголовочном файле
<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, 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 с использованием генератора псевдослучайных чисел, если нет поддержки не-детерминированной генерации случайных чисел.
(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) |
производит вещественные значения по F-распределению Фишера. (шаблон класса) |
(C++11) |
производит вещественные значения по распределению Стьюдента. (шаблон класса) |
Распределения выборки | |
(C++11) |
производит случайные целые числа по дискретному распределению (шаблон класса) |
| выдаёт вещественные значения, распределённые по константным подынтервалам (шаблон класса) | |
| выдаёт вещественные значения, распределяемые по определённым интервалам (шаблон класса) | |
Утилиты
Определены в заголовочном файле
<random> | |
(C++11) |
равномерно распределяет вещественные значения заданной точности по [0, 1) (шаблон функции) |
(C++11) |
универсальный генератор скремблированных исходных последовательностей с устранением смещения (класс) |
Библиотека случайных чисел C
В дополнение к генераторам и распределениям, описанным выше, также доступны функции и константы из библиотеки случайных чисел C, хотя это не рекомендуется:
Определены в заголовочном файле
<cstdlib> | |
| генерирует псевдослучайные числа (функция) | |
| инициализирует псевдогенератор случайных чисел (функция) | |
| максимально возможное значение, генерируемое 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
Смотрите также
Документация C по Генерация псевдослучайных чисел
|