C++-Standardbibliothek <random>

In der C++-Standardbibliothek<random>Die Header-Datei bietet eine Reihe von Werkzeugen zum Generieren von Zufallszahlen, die alles von einfachen Gleichverteilungen bis hin zu komplexen diskreten Verteilungen abdecken und eine breite Palette von Optionen für Anwendungen bieten, die Zufallszahlen benötigen. Diese Werkzeuge sind in Bereichen wie Simulation, Spieleentwicklung und kryptografischen Algorithmen sehr nützlich.

<random>Es unterstützt nicht nur die Generierung von Pseudozufallszahlen, sondern auch Seed-Steuerung, verschiedene Wahrscheinlichkeitsverteilungen usw., sodass Entwickler flexibel Sequenzen von Zufallszahlen generieren können, die bestimmte Anforderungen erfüllen.

<random>Die Bibliothek besteht aus den folgenden drei Hauptkomponenten:

  1. Zufallszahlen-Engine: Der Kern zur Generierung von Pseudozufallszahlen, der verwendet wird, um die Reproduzierbarkeit und Zufälligkeit des Generierungsprozesses zu steuern.
  2. Zufallszahlen-Verteilung: Steuert den Typ der Wahrscheinlichkeitsverteilung, der die generierten Werte folgen.
  3. Zufallszahlen-Adapter: ermöglicht die Anpassung des Engine-Verhaltens, wie z. B.discard_blockund andere Adapter.

In C++ können Zufallszahlengeneratoren (Random Number Generator, RNG) in zwei Hauptkategorien unterteilt werden:

  • Pseudozufallszahlengenerator: Sie verwenden deterministische Algorithmen, um scheinbar zufällige Sequenzen zu erzeugen. Diese Sequenzen sind theoretisch vorhersagbar, aber für die meisten Anwendungen im Allgemeinen zufällig genug.
  • Echter Zufallszahlengenerator: Sie erzeugen Zufallszahlen basierend auf physikalischen Prozessen (wie thermisches Rauschen, radioaktiver Zerfall usw.), aber die C++-Standardbibliothek stellt solche Generatoren nicht direkt bereit.

Gängige Zufallszahlen-Engines

EngineBeschreibung
std::default_random_engineStandard-Zufallszahlen-Engine, mit einer Implementierung, die vom jeweiligen Compiler abhängt.
std::minstd_randLineare Kongruenz-Engine, die eine gleichmäßige Sequenz von Pseudozufallszahlen erzeugt.
std::mt19937Mersenne-Twister-Algorithmus, geeignet für allgemeine Zufallszahlengenerierung.
std::mt19937_6464-Bit-Mersenne-Twister-Algorithmus.
std::ranlux24_baseVereinfachte Subtract-with-Carry-Engine, die für die hochwertige Generierung verwendet wird.
std::knuth_bKnuth-Shuffle-Zufallszahlengenerator.

Gängige Engines wie z. B.std::mt19937Aufgrund seiner schnellen Generierungsgeschwindigkeit und hohen Generierungsqualität ist es eine weithin empfohlene Engine zur Zufallszahlengenerierung. Der Generator kann außerdemseed()Methode zum Festlegen des Seeds, die die Generierung reproduzierbarer Pseudozufallssequenzen erleichtert.

Typen von Zufallszahlenverteilungen

1. Gleichverteilung

DistributionBeschreibung
std::uniform_int_distributionErzeugt eine Gleichverteilung über einen Bereich von Ganzzahlen.
std::uniform_real_distributionErzeugt eine Gleichverteilung über einen Bereich von Gleitkommazahlen.
std::mt19937 gen(seed);
std::uniform_int_distribution<int> dist(1, 100); // 生成 1 到 100 间的整数
int random_int = dist(gen);

2. Normalverteilung

DistributionBeschreibung
std::normal_distributionStandardnormalverteilung, zentralsymmetrisch, wird oft zur Simulation natürlicher Phänomene verwendet.
std::lognormal_distributionLog-Normalverteilung.
std::mt19937 gen(seed);
std::normal_distribution<> dist(0, 1); // 平均值为0,标准差为1
double random_normal = dist(gen);

3. Diskrete Verteilung

DistributionBeschreibung
std::discrete_distributionErzeugt Zufallszahlen als Ganzzahlen mit einer Menge spezifischer Wahrscheinlichkeiten.
std::bernoulli_distributionBernoulli-Verteilung, die nur erzeugttrueoderfalse。
std::binomial_distributionBinomialverteilung.
std::mt19937 gen(seed);
std::discrete_distribution<int> dist({40, 10, 50}); // 概率为40%、10%、50%
int random_discrete = dist(gen);

Syntax

Nutzung<random>Die grundlegenden Schritte der Bibliothek sind wie folgt:

  • Header-Dateien einbinden<random>。
  • Erstellen Sie ein Zufallszahlengenerator-Objekt.
  • Verwenden Sie die Verteilungsklasse, um Zufallszahlen zu erzeugen.

Beispiel

Grundlegende Zufallszahlen erzeugen

Beispiel

#include <iostream>
#include <random>

int main() {
    // Verwenden Sie ein Random-Device, um einen zufälligen Startwert zu erzeugen
    std::random_device rd;
   
    // Verwenden Sie den Zufallsstartwert, um den Mersenne-Twister-Zufallszahlengenerator zu initialisieren
    std::mt19937 generator(rd());

    // Eine Zufallszahl erzeugen
    std::cout << "Zufallszahl: " << generator() << std::endl;

    return 0;
}

Ausgabeergebnis:

Random number: 3499211612

Hinweis:Jedes Mal, wenn das Programm ausgeführt wird, können die generierten Zufallszahlen unterschiedlich sein.

Verwendung einer Gleichverteilung

Beispiel

#include <iostream>
#include <random>

int main() {
    // Einen Zufallszahlengenerator erstellen
    std::mt19937 generator;

    // Einen gleichverteilten Zufallszahlengenerator mit einem Bereich von 1 bis 10 erstellen
    std::uniform_int_distribution<int> distribution(1, 10);

    // 5 Zufallszahlen erzeugen und ausgeben
    for (int i = 0; i < 5; ++i) {
        std::cout << "Zufallszahl: " << distribution(generator) << std::endl;
    }

    return 0;
}

Ausgabeergebnis:

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

Jedes Mal, wenn das Programm ausgeführt wird, kann die ausgegebene Zufallszahlenfolge unterschiedlich sein.

Verwendung einer Normalverteilung

Beispiel

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

int main() {
    // Einen Zufallszahlengenerator erstellen
    std::mt19937 generator;

    // Einen normalverteilten Zufallszahlengenerator mit Mittelwert 0 und Standardabweichung 1 erstellen
    std::normal_distribution<double> distribution(0.0, 1.0);

    // Ausgabeformat auf zwei Dezimalstellen setzen
    std::cout << std::fixed << std::setprecision(2);

    // 5 Zufallszahlen erzeugen und ausgeben
    for (int i = 0; i < 5; ++i) {
        std::cout << "Zufallszahl: " << 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

Verwendung der mt19937-Engine zur Generierung von Zufallszahlen mit verschiedenen Verteilungen:

Beispiel

#include <iostream>
#include <random>

int main() {
    // 1. Seed und Zufallszahlen-Engine setzen
    std::random_device rd; // Zufallsgerät erzeugt den Seed
    std::mt19937 gen(rd()); // Mersenne-Twister-Engine

    // 2. Gleichverteilte Ganzzahlen
    std::uniform_int_distribution<> dist_int(1, 100);
    std::cout << "Gleichverteilte Ganzzahl: " << dist_int(gen) << std::endl;

    // 3. Gleichverteilte Gleitkommazahlen
    std::uniform_real_distribution<> dist_real(0.0, 1.0);
    std::cout << "Gleichverteilt reell: " << dist_real(gen) << std::endl;

    // 4. Normalverteilung
    std::normal_distribution<> dist_normal(0, 1);
    std::cout << "Normal: " << dist_normal(gen) << std::endl;

    // 5. Diskrete Verteilung
    std::discrete_distribution<> dist_discrete({10, 20, 70});
    std::cout << "Diskret: " << dist_discrete(gen) << std::endl;

    return 0;
}

Zufallszahlen-Adapter

Zufallszahlen-Adapter ermöglichen die Anpassung des Erzeugungsverhaltens; es gibt zwei Haupttypen von Adaptern:

  1. std::discard_block_engine: Verwirft eine bestimmte Anzahl generierter Werte und behält nur diejenigen in festgelegten Abständen bei, wird verwendet, um die Zufälligkeit zu reduzieren.
  2. std::independent_bits_engine: Erzeugt Zufallszahlen mit einer festgelegten Anzahl von Bits, wodurch sich direkt Binärdaten einfach erzeugen lassen.

Beispiel

#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-Zufallszahl: " << discard_engine() << std::endl;

    return 0;
}

Häufige Verwendung

  • Verwenden Sie einen Seed, um eine reproduzierbare Zufallsfolge zu erzeugen: Die Angabe desselben Seeds bewirkt, dass jeder Lauf dieselbe Folge erzeugt.
  • Zufallszahlen mit unterschiedlichen Verteilungen erzeugen: Wählen Sie eine Verteilungsfunktion, die zum Anwendungsszenario passt, um reale Probleme besser zu simulieren.
  • Anpassen der Generatorleistung: Verwenden Sie verschiedene Zufalls-Engines, um Erzeugungsleistung und Genauigkeit auszubalancieren.
Weitere Erweiterungen