Bibliothèque standard C++ <random>

Dans la bibliothèque standard C++<random>Le fichier d'en-tête fournit un ensemble d'outils pour générer des nombres aléatoires, couvrant tout, des simples distributions uniformes aux distributions discrètes complexes, offrant un large éventail d'options pour les applications qui nécessitent des nombres aléatoires. Ces outils sont très utiles dans des domaines tels que la simulation, le développement de jeux et les algorithmes cryptographiques.

<random>Il prend non seulement en charge la génération de nombres pseudo-aléatoires, mais aussi le contrôle de graine, diverses distributions de probabilité, etc., permettant aux développeurs de générer de manière flexible des séquences de nombres aléatoires répondant à des exigences spécifiques.

<random>La bibliothèque se compose des trois principaux composants suivants :

  1. Moteur de nombres aléatoires: Le cœur de la génération de nombres pseudo-aléatoires, utilisé pour contrôler la reproductibilité et le caractère aléatoire du processus de génération.
  2. Distribution de nombres aléatoires: Contrôle le type de distribution de probabilité que suivent les valeurs générées.
  3. Adaptateur de nombres aléatoires: permet d'ajuster le comportement du moteur, tel quediscard_blocket d'autres adaptateurs.

En C++, les générateurs de nombres aléatoires (Random Number Generator, RNG) peuvent être divisés en deux catégories principales :

  • Générateur de nombres pseudo-aléatoires: ils utilisent des algorithmes déterministes pour générer des séquences apparemment aléatoires. Ces séquences sont théoriquement prévisibles, mais sont généralement suffisamment aléatoires pour la plupart des applications.
  • Générateur de nombres véritablement aléatoires: ils génèrent des nombres aléatoires à partir de processus physiques (tels que le bruit thermique, la désintégration radioactive, etc.), mais la bibliothèque standard C++ ne fournit pas directement de tels générateurs.

Moteurs de génération de nombres aléatoires courants

MoteurDescription
std::default_random_engineMoteur de nombres aléatoires par défaut, avec une implémentation qui dépend du compilateur spécifique.
std::minstd_randMoteur congruentiel linéaire, produisant une séquence uniforme de nombres pseudo-aléatoires.
std::mt19937Algorithme Mersenne Twister, adapté à la génération de nombres aléatoires à usage général.
std::mt19937_64Algorithme Mersenne Twister 64 bits.
std::ranlux24_baseMoteur simplifié « subtract-with-carry », utilisé pour une génération de haute qualité.
std::knuth_bGénérateur de nombres aléatoires par mélange de Knuth.

Moteurs courants tels questd::mt19937En raison de sa vitesse de génération rapide et de sa qualité de génération élevée, c'est un moteur de génération de nombres aléatoires largement recommandé. Le générateur peut également utiliserseed()Méthode pour spécifier la graine, facilitant la génération de séquences pseudo-aléatoires reproductibles.

Types de distribution de nombres aléatoires

1. Distribution uniforme

DistributionDescription
std::uniform_int_distributionGénère une distribution uniforme sur un intervalle d'entiers.
std::uniform_real_distributionGénère une distribution uniforme sur un intervalle de nombres à virgule flottante.
std::mt19937 gen(seed);
std::uniform_int_distribution<int> dist(1, 100); // 生成 1 到 100 间的整数
int random_int = dist(gen);

2. Distribution normale

DistributionDescription
std::normal_distributionDistribution normale standard, à symétrie centrale, souvent utilisée pour simuler des phénomènes naturels.
std::lognormal_distributionDistribution log-normale.
std::mt19937 gen(seed);
std::normal_distribution<> dist(0, 1); // 平均值为0,标准差为1
double random_normal = dist(gen);

3. Distribution discrète

DistributionDescription
std::discrete_distributionGénère des nombres aléatoires sous forme d'entiers avec un ensemble de probabilités spécifiques.
std::bernoulli_distributionDistribution de Bernoulli, qui ne génère quetrueoufalse。
std::binomial_distributionLoi binomiale.
std::mt19937 gen(seed);
std::discrete_distribution<int> dist({40, 10, 50}); // 概率为40%、10%、50%
int random_discrete = dist(gen);

Syntaxe

Utilisation<random>Les étapes de base de la bibliothèque sont les suivantes :

  • Inclure les fichiers d'en-tête<random>。
  • Créez un objet générateur de nombres aléatoires.
  • Utilisez la classe de distribution pour générer des nombres aléatoires.

Exemple

Générer des nombres aléatoires de base

Exemple

#include <iostream>
#include <random>

int main() {
    // Utiliser un dispositif aléatoire pour créer une graine aléatoire
    std::random_device rd;
   
    // Utiliser la graine aléatoire pour initialiser le générateur de nombres aléatoires Mersenne Twister
    std::mt19937 generator(rd());

    // Générer un nombre aléatoire
    std::cout << "Nombre aléatoire : " << generator() << std::endl;

    return 0;
}

Résultat de sortie :

Random number: 3499211612

Remarque :Chaque fois que le programme s'exécute, les nombres aléatoires générés peuvent être différents.

Utilisation d'une distribution uniforme

Exemple

#include <iostream>
#include <random>

int main() {
    // Créer un générateur de nombres aléatoires
    std::mt19937 generator;

    // Créer un générateur de nombres aléatoires suivant une distribution uniforme avec une plage de 1 à 10
    std::uniform_int_distribution<int> distribution(1, 10);

    // Générer et afficher 5 nombres aléatoires
    for (int i = 0; i < 5; ++i) {
        std::cout << "Nombre aléatoire : " << distribution(generator) << std::endl;
    }

    return 0;
}

Résultat de sortie :

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

Chaque fois que le programme s'exécute, la séquence de nombres aléatoires produite peut être différente.

Utilisation d'une distribution normale

Exemple

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

int main() {
    // Créer un générateur de nombres aléatoires
    std::mt19937 generator;

    // Créer un générateur de nombres aléatoires suivant une distribution normale avec une moyenne de 0 et un écart-type de 1
    std::normal_distribution<double> distribution(0.0, 1.0);

    // Définir le format de sortie à deux décimales
    std::cout << std::fixed << std::setprecision(2);

    // Générer et afficher 5 nombres aléatoires
    for (int i = 0; i < 5; ++i) {
        std::cout << "Nombre aléatoire : " << 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

Utilisation du moteur mt19937 pour générer des nombres aléatoires avec différentes distributions :

Exemple

#include <iostream>
#include <random>

int main() {
    // 1. Définir la graine et le moteur de nombres aléatoires
    std::random_device rd; // Le dispositif aléatoire génère la graine
    std::mt19937 gen(rd()); // Moteur Mersenne Twister

    // 2. Entiers uniformément distribués
    std::uniform_int_distribution<> dist_int(1, 100);
    std::cout << "Entier uniforme : " << dist_int(gen) << std::endl;

    // 3. Nombres à virgule flottante uniformément distribués
    std::uniform_real_distribution<> dist_real(0.0, 1.0);
    std::cout << "Réel uniforme : " << dist_real(gen) << std::endl;

    // 4. Loi normale
    std::normal_distribution<> dist_normal(0, 1);
    std::cout << "Normale : " << dist_normal(gen) << std::endl;

    // 5. Loi discrète
    std::discrete_distribution<> dist_discrete({10, 20, 70});
    std::cout << "Discrète : " << dist_discrete(gen) << std::endl;

    return 0;
}

Adaptateur de nombres aléatoires

Les adaptateurs de nombres aléatoires permettent d'ajuster le comportement de génération ; il existe deux principaux types d'adaptateurs :

  1. std::discard_block_engine: Rejette un certain nombre de valeurs générées et ne conserve que celles qui se trouvent à des intervalles spécifiés, utilisé pour réduire le caractère aléatoire.
  2. std::independent_bits_engine: Génère des nombres aléatoires avec un nombre de bits spécifié, ce qui facilite la génération directe de données binaires.

Exemple

#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 << "Nombre aléatoire du bloc discard : " << discard_engine() << std::endl;

    return 0;
}

Utilisation courante

  • Utiliser une graine pour générer une séquence aléatoire reproductible: spécifier la même graine fait que chaque exécution génère la même séquence.
  • Générer des nombres aléatoires avec différentes distributions: Choisissez une fonction de distribution adaptée au scénario d'application pour mieux simuler des problèmes du monde réel.
  • Ajustement des performances du générateur: Utilisez différents moteurs aléatoires pour équilibrer les performances de génération et la précision.
autres extensions