Spec-Zone.ru › C++

Генерация псевдослучайных чисел

Библиотека случайных чисел предоставляет классы для генерации случайных и псевдослучайных чисел. Эти классы включают:

  • Генераторы случайных битов равномерного распределения (URBG), которые включают в себя как генераторы случайных чисел, которые являются псевдослучайными генераторами чисел, генерирующими целые последовательности с равномерным распределением, так и истинные генераторы случайных чисел, если они доступны;
  • Распределения случайных чисел (например, равномерное, нормальное или распределения Пуассона), которые преобразуют выходные данные URBG в различные статистические распределения.

URBG и распределения предназначены для совместного использования для получения случайных значений. Все генераторы случайных чисел могут быть специально инициализированы, сериализованы и десериализованы для использования с повторяемыми симуляторами.

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

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

Все генераторы случайных битов равномерного распределения соответствуют требованиям UniformRandomBitGenerator. C++20 также определяет концепцию uniform_random_bit_generator.

Определено в заголовочном файле <random>
uniform_random_bit_generator
(C++20)
указывает, что тип соответствует генератору случайных битов равномерного распределения
(концепция)

Генераторы случайных чисел

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

Выбор генератора зависит от компромиссов: линейный конгруэнтный генератор умеренно быстрый и требует очень небольшого объема памяти для состояния. Генераторы Легированных Фибоначчи очень быстры даже на процессорах без продвинутых наборов инструкций арифметики, за счет большего объёма памяти для состояния и иногда менее желательных спектральных характеристик. Генератор Мерсенна Твистера медленнее и требует большего объёма памяти для состояния, но с правильными параметрами обладает самой длинной не повторяющейся последовательностью с наиболее желательными спектральными характеристиками (для данного определения желательных).

Ни один из генераторов случайных чисел, предоставляемых стандартной библиотекой, не является криптографически безопасным. Как и при любой безопасной операции, для этой цели следует использовать библиотеку криптографии (например, OpenSSL RAND_bytes).

Определено в заголовочном файле <random>
linear_congruential_engine
(C++11)
реализует алгоритм линейного конгруэнтного
(шаблон класса)
mersenne_twister_engine
(C++11)
реализует алгоритм Мерсенна Твистера
(шаблон класса)
subtract_with_carry_engine
(C++11)
реализует алгоритм вычитания с переносом (Легированный Фибоначчи)
(шаблон класса)

Адаптеры генераторов случайных чисел

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

Определено в заголовочном файле <random>
discard_block_engine
(C++11)
отбрасывает часть выходных данных генератора случайных чисел
(шаблон класса)
independent_bits_engine
(C++11)
упаковывает выходные данные генератора случайных чисел в блоки заданного количества битов
(шаблон класса)
shuffle_order_engine
(C++11)
предоставляет выходные данные генератора случайных чисел в другом порядке
(шаблон класса)

Предопределенные генераторы случайных чисел

Несколько конкретных популярных алгоритмов предопределены.

Определено в заголовочном файле <random>
Тип Определение
minstd_rand0 (C++11) std::linear_congruential_engine<std::uint_fast32_t, 16807, 0, 2147483647>

Разработан в 1969 году Lewis, Goodman и Miller, принят как «Минимальный стандарт» в 1988 году Park и Miller

minstd_rand (C++11) std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647>

Новый «Минимальный стандарт», рекомендованный Park, Miller и Stockmeyer в 1993 году

mt19937(C++11)

std::mersenne_twister_engine<std::uint_fast32_t, 32, 624, 397, 31,
0x9908b0df, 11,
0xffffffff, 7,
0x9d2c5680, 15,
0xefc60000, 18, 1812433253>

32-битный генератор Мерсенна Твистера Matsumoto и Nishimura, 1998

mt19937_64(C++11)

std::mersenne_twister_engine<std::uint_fast64_t, 64, 312, 156, 31,
0xb5026f5aa96619e9, 29,
0x5555555555555555, 17,
0x71d67fffeda60000, 37,
0xfff7eee000000000, 43, 6364136223846793005>

64-битный генератор Мерсенна Твистера Matsumoto и Nishimura, 2000

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 Martin Lüscher и Fred James, 1994

ranlux48(C++11) std::discard_block_engine<std::ranlux48_base, 389, 11>

48-битный генератор RANLUX Martin Lüscher и Fred James, 1994

knuth_b (C++11) std::shuffle_order_engine<std::minstd_rand0, 256>
default_random_engine(C++11) определяется реализацией

Недетерминированные случайные числа

std::random_device — это недетерминированный генератор случайных битов равномерного распределения, хотя реализациям разрешено реализовывать std::random_device с использованием генератора псевдослучайных чисел, если нет поддержки генерации недетерминированных случайных чисел.

random_device
(C++11)
недетерминированный генератор случайных чисел, использующий аппаратный источник энтропии
(класс)

Распределения случайных чисел

Распределение случайных чисел постобрабатывает выходные данные URBG таким образом, чтобы полученные выходные данные распределялись в соответствии с определённой статистической функцией плотности вероятности.

Распределения случайных чисел соответствуют RandomNumberDistribution.

Определено в заголовке <random>
Равномерные распределения
uniform_int_distribution
(C++11)
генерирует целые значения, равномерно распределённые в заданном диапазоне
(шаблон класса)
uniform_real_distribution
(C++11)
генерирует вещественные значения, равномерно распределённые в заданном диапазоне
(шаблон класса)
Распределения Бернулли
bernoulli_distribution
(C++11)
генерирует значения на основе распределения Бернулли
(класс)
binomial_distribution
(C++11)
генерирует целые значения на основе биномиального распределения
(шаблон класса)
negative_binomial_distribution
(C++11)
генерирует целые значения на основе распределения отрицательного биномиального
(шаблон класса)
geometric_distribution
(C++11)
генерирует целые значения на основе геометрического распределения
(шаблон класса)
Распределения Пуассона
poisson_distribution
(C++11)
генерирует целые значения на основе распределения Пуассона
(шаблон класса)
exponential_distribution
(C++11)
генерирует вещественные значения на основе экспоненциального распределения
(шаблон класса)
gamma_distribution
(C++11)
генерирует вещественные значения на основе гамма-распределения
(шаблон класса)
weibull_distribution
(C++11)
генерирует вещественные значения на основе распределения Вейбулла
(шаблон класса)
extreme_value_distribution
(C++11)
генерирует вещественные значения на основе распределения экстремальных значений
(шаблон класса)
Нормальные распределения
normal_distribution
(C++11)
генерирует вещественные значения на основе стандартного нормального (гауссовского) распределения
(шаблон класса)
lognormal_distribution
(C++11)
генерирует вещественные значения на основе логарифмически нормального распределения
(шаблон класса)
chi_squared_distribution
(C++11)
генерирует вещественные значения на основе распределения хи-квадрат
(шаблон класса)
cauchy_distribution
(C++11)
генерирует вещественные значения на основе распределения Коши
(шаблон класса)
fisher_f_distribution
(C++11)
генерирует вещественные значения на основе распределения Фишера F
(шаблон класса)
student_t_distribution
(C++11)
генерирует вещественные значения на основе распределения Стьюдента t
(шаблон класса)
Распределения выборки
discrete_distribution
(C++11)
генерирует случайные целые числа на основе дискретного распределения
(шаблон класса)
piecewise_constant_distribution
(C++11)
генерирует вещественные значения, распределённые по постоянным подынтервалам
(шаблон класса)
piecewise_linear_distribution
(C++11)
генерирует вещественные значения, распределённые по заданным подынтервалам
(шаблон класса)

Справочные средства

Определено в заголовке <random>
generate_canonical
(C++11)
равномерно распределяет вещественные значения заданной точности по [​0​, 1)
(шаблон функции)
seed_seq
(C++11)
генератор последовательностей семян для устранения смещения
(класс)

Библиотека C для генерации случайных чисел

Помимо описанных выше генераторов и распределений, доступны также функции и константы из библиотеки C для генерации случайных чисел, хотя их использование не рекомендуется:

Определено в заголовке <cstdlib>
rand
генерирует псевдослучайное число
(функция)
srand
инициализирует генератор псевдослучайных чисел
(функция)
RAND_MAX
максимальное возможное значение, генерируемое 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/w/cpp/numeric/random

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API