Стандартная библиотека C++ <random>

В стандартной библиотеке C++<random>Заголовочный файл предоставляет набор инструментов для генерации случайных чисел, охватывающий всё от простых равномерных распределений до сложных дискретных распределений, предлагая широкий выбор возможностей для приложений, которым требуются случайные числа. Эти инструменты очень полезны в таких областях, как моделирование, разработка игр и криптографические алгоритмы.

<random>Он не только поддерживает генерацию псевдослучайных чисел, но также поддерживает управление начальным значением, различные вероятностные распределения и т. д., позволяя разработчикам гибко генерировать последовательности случайных чисел, отвечающие конкретным требованиям.

<random>Библиотека состоит из следующих трёх основных компонентов:

  1. Движок генерации случайных чисел: ядро генерации псевдослучайных чисел, используется для управления воспроизводимостью и случайностью процесса генерации.
  2. Распределение случайных чисел: управляет типом вероятностного распределения, которому подчиняются сгенерированные значения.
  3. Адаптер генератора случайных чисел: позволяет настраивать поведение движка, напримерdiscard_blockи другие адаптеры.

В C++ генераторы случайных чисел (Random Number Generator, RNG) можно разделить на две основные категории:

  • Генератор псевдослучайных чисел: Они используют детерминированные алгоритмы для генерации кажущихся случайными последовательностей. Эти последовательности теоретически предсказуемы, но обычно достаточно случайны для большинства приложений.
  • Генератор истинно случайных чисел: Они генерируют случайные числа на основе физических процессов (таких как тепловой шум, радиоактивный распад и т. д.), но стандартная библиотека C++ не предоставляет такие генераторы напрямую.

Распространённые движки случайных чисел

ДвижокОписание
std::default_random_engineДвижок случайных чисел по умолчанию, реализация которого зависит от конкретного компилятора.
std::minstd_randЛинейный конгруэнтный движок, генерирующий равномерную последовательность псевдослучайных чисел.
std::mt19937Алгоритм Mersenne Twister, подходящий для генерации случайных чисел общего назначения.
std::mt19937_6464-битный алгоритм Mersenne Twister.
std::ranlux24_baseУпрощённый движок subtract-with-carry, используемый для высококачественной генерации.
std::knuth_bГенератор случайных чисел с тасованием Кнута.

Распространённые движки, такие какstd::mt19937Благодаря высокой скорости генерации и высокому качеству генерации это широко рекомендуемый движок генерации случайных чисел. Генератор также может использоватьseed()Метод указания seed, позволяющий генерировать воспроизводимые псевдослучайные последовательности.

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

1. Равномерное распределение

ДистрибутивОписание
std::uniform_int_distributionГенерирует равномерное распределение в диапазоне целых чисел.
std::uniform_real_distributionГенерирует равномерное распределение в диапазоне чисел с плавающей запятой.
std::mt19937 gen(seed);
std::uniform_int_distribution<int> dist(1, 100); // 生成 1 到 100 间的整数
int random_int = dist(gen);

2. Нормальное распределение

ДистрибутивОписание
std::normal_distributionСтандартное нормальное распределение, центрально симметричное, часто используется для моделирования природных явлений.
std::lognormal_distributionЛогнормальное распределение.
std::mt19937 gen(seed);
std::normal_distribution<> dist(0, 1); // 平均值为0,标准差为1
double random_normal = dist(gen);

3. Дискретное распределение

ДистрибутивОписание
std::discrete_distributionГенерирует случайные числа в виде целых чисел с заданным набором вероятностей.
std::bernoulli_distributionРаспределение Бернулли, которое генерирует толькоtrueилиfalse。
std::binomial_distributionБиномиальное распределение.
std::mt19937 gen(seed);
std::discrete_distribution<int> dist({40, 10, 50}); // 概率为40%、10%、50%
int random_discrete = dist(gen);

Синтаксис

Использование<random>Основные шаги работы с библиотекой следующие:

  • Включение заголовочных файлов<random>。
  • Создайте объект генератора случайных чисел.
  • Используйте класс распределения для генерации случайных чисел.

Пример

Сгенерируйте базовые случайные числа

Пример

#include <iostream>
#include <random>

int main() {
    // Используйте устройство случайных чисел для создания случайного начального значения
    std::random_device rd;
   
    // Используйте случайное начальное значение для инициализации генератора случайных чисел Mersenne Twister
    std::mt19937 generator(rd());

    // Сгенерируйте случайное число
    std::cout << "Случайное число: " << generator() << std::endl;

    return 0;
}

Результат вывода:

Random number: 3499211612

Примечание:Каждый раз при запуске программы сгенерированные случайные числа могут быть разными.

Использование равномерного распределения

Пример

#include <iostream>
#include <random>

int main() {
    // Создать генератор случайных чисел
    std::mt19937 generator;

    // Создать генератор равномерно распределённых случайных чисел в диапазоне от 1 до 10
    std::uniform_int_distribution<int> distribution(1, 10);

    // Сгенерировать и вывести 5 случайных чисел
    for (int i = 0; i < 5; ++i) {
        std::cout << "Случайное число: " << distribution(generator) << std::endl;
    }

    return 0;
}

Результат вывода:

Random number: 7
Random number: 10
Random number: 6
Random number: 2
Random number: 4

Каждый раз при запуске программы выводимая последовательность случайных чисел может быть разной.

Использование нормального распределения

Пример

#include <iostream>
#include <random>
#include <iomanip>

int main() {
    // Создать генератор случайных чисел
    std::mt19937 generator;

    // Создать генератор нормально распределённых случайных чисел со средним 0 и стандартным отклонением 1
    std::normal_distribution<double> distribution(0.0, 1.0);

    // Установить формат вывода с двумя знаками после запятой
    std::cout << std::fixed << std::setprecision(2);

    // Сгенерировать и вывести 5 случайных чисел
    for (int i = 0; i < 5; ++i) {
        std::cout << "Случайное число: " << distribution(generator) << std::endl;
    }

    return 0;
}
Random number: -0.15
Random number: 0.13
Random number: -1.87
Random number: 0.46
Random number: -0.21

Использование движка mt19937 для генерации случайных чисел с различными распределениями:

Пример

#include <iostream>
#include <random>

int main() {
    // 1. Установить seed и движок генератора случайных чисел
    std::random_device rd; // random_device генерирует seed
    std::mt19937 gen(rd()); // Движок Mersenne Twister

    // 2. Равномерно распределённые целые числа
    std::uniform_int_distribution<> dist_int(1, 100);
    std::cout << "Равномерное целое: " << dist_int(gen) << std::endl;

    // 3. Равномерно распределённые числа с плавающей запятой
    std::uniform_real_distribution<> dist_real(0.0, 1.0);
    std::cout << "Равномерное вещественное: " << dist_real(gen) << std::endl;

    // 4. Нормальное распределение
    std::normal_distribution<> dist_normal(0, 1);
    std::cout << "Нормальное: " << dist_normal(gen) << std::endl;

    // 5. Дискретное распределение
    std::discrete_distribution<> dist_discrete({10, 20, 70});
    std::cout << "Дискретное: " << dist_discrete(gen) << std::endl;

    return 0;
}

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

Адаптеры генератора случайных чисел позволяют настраивать поведение генерации; существует два основных типа адаптеров:

  1. std::discard_block_engine: Отбрасывает определённое количество сгенерированных значений и сохраняет только те, которые находятся на заданных интервалах; используется для уменьшения случайности.
  2. std::independent_bits_engine: Генерирует случайные числа с заданным числом битов, что позволяет легко напрямую генерировать двоичные данные.

Пример

#include <iostream>
#include <random>

int main() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::discard_block_engine<std::mt19937, 3, 2> discard_engine(gen);
    std::cout << "Случайное число discard block: " << discard_engine() << std::endl;

    return 0;
}

Типичное использование

  • Используйте начальное значение для генерации воспроизводимой случайной последовательности: указание одного и того же начального значения заставляет каждый запуск генерировать одну и ту же последовательность.
  • Генерируйте случайные числа с разными распределениями: выберите функцию распределения, соответствующую сценарию применения, чтобы лучше моделировать реальные задачи.
  • Настройка производительности генератора: используйте разные случайные движки, чтобы балансировать производительность и точность генерации.
Другие расширения