C++
Zufallszahlengenerierung
Suche…
Bemerkungen
Die Erzeugung von <random>
in C ++ wird vom Header <random>
bereitgestellt. Dieser Header definiert Zufallsgeräte, Pseudozufallsgeneratoren und Verteilungen.
Zufällige Geräte geben vom Betriebssystem bereitgestellte Zufallszahlen zurück. Sie sollten entweder zur Initialisierung von Pseudozufallsgeneratoren oder direkt für kryptographische Zwecke verwendet werden.
Pseudozufallsgeneratoren geben basierend auf ihrem Anfangsstart ganzzahlige Pseudozufallszahlen zurück. Der Pseudozufallszahlenbereich umfasst typischerweise alle Werte eines vorzeichenlosen Typs. Alle Pseudo-Zufallsgeneratoren in der Standardbibliothek geben für alle Plattformen die gleichen Zahlen für denselben Anfangswert aus.
Verteilungen verbrauchen Zufallszahlen von Pseudozufallsgeneratoren oder Zufallsvorrichtungen und erzeugen Zufallszahlen mit der erforderlichen Verteilung. Distributionen sind nicht plattformunabhängig und können unterschiedliche Nummern für dieselben Generatoren mit demselben Start-Seed auf verschiedenen Plattformen erzeugen.
Echter Zufallswertgenerator
Um echte Zufallswerte zu erzeugen, die für die Kryptographie verwendet werden können, muss std::random_device
als Generator verwendet werden.
#include <iostream>
#include <random>
int main()
{
std::random_device crypto_random_generator;
std::uniform_int_distribution<int> int_distribution(0,9);
int actual_distribution[10] = {0,0,0,0,0,0,0,0,0,0};
for(int i = 0; i < 10000; i++) {
int result = int_distribution(crypto_random_generator);
actual_distribution[result]++;
}
for(int i = 0; i < 10; i++) {
std::cout << actual_distribution[i] << " ";
}
return 0;
}
std::random_device
wird auf dieselbe Weise verwendet wie ein Pseudo-Zufallswertgenerator.
std::random_device
kann jedoch im Hinblick auf eine implementierungsdefinierte Pseudozufallszahlen-Engine implementiert werden, wenn eine nicht deterministische Quelle (z. B. ein Hardwaregerät) für die Implementierung nicht verfügbar ist.
Das Erkennen solcher Implementierungen sollte über die entropy
Member-Funktion möglich sein (die Null zurückgibt, wenn der Generator vollständig deterministisch ist), aber viele gängige Bibliotheken (sowohl GCCs libstdc ++ als auch LLVMs libc ++) geben immer null zurück, selbst wenn sie qualitativ hochwertige externe Zufälligkeiten verwenden .
Generierung einer Pseudo-Zufallszahl
Ein Pseudo-Zufallszahlengenerator generiert Werte, die basierend auf zuvor generierten Werten geschätzt werden können. Mit anderen Worten: es ist deterministisch. Verwenden Sie keinen Pseudo-Zufallszahlengenerator in Situationen, in denen eine echte Zufallszahl erforderlich ist.
#include <iostream>
#include <random>
int main()
{
std::default_random_engine pseudo_random_generator;
std::uniform_int_distribution<int> int_distribution(0, 9);
int actual_distribution[10] = {0,0,0,0,0,0,0,0,0,0};
for(int i = 0; i < 10000; i++) {
int result = int_distribution(pseudo_random_generator);
actual_distribution[result]++;
}
for(int i = 0; i <= 9; i++) {
std::cout << actual_distribution[i] << " ";
}
return 0;
}
Dieser Code erstellt einen Zufallszahlengenerator und eine Verteilung, die mit gleicher Wahrscheinlichkeit Ganzzahlen im Bereich [0,9] generiert. Es zählt dann, wie oft jedes Ergebnis generiert wurde.
Der Vorlagenparameter von std::uniform_int_distribution<T>
gibt den Typ der Ganzzahl an, die generiert werden soll. Verwenden Sie std::uniform_real_distribution<T>
, um Floats oder Doubles zu generieren.
Verwendung des Generators für mehrere Distributionen
Der Zufallszahlengenerator kann (und sollte) für mehrere Verteilungen verwendet werden.
#include <iostream>
#include <random>
int main()
{
std::default_random_engine pseudo_random_generator;
std::uniform_int_distribution<int> int_distribution(0, 9);
std::uniform_real_distribution<float> float_distribution(0.0, 1.0);
std::discrete_distribution<int> rigged_dice({1,1,1,1,1,100});
std::cout << int_distribution(pseudo_random_generator) << std::endl;
std::cout << float_distribution(pseudo_random_generator) << std::endl;
std::cout << (rigged_dice(pseudo_random_generator) + 1) << std::endl;
return 0;
}
In diesem Beispiel ist nur ein Generator definiert. Anschließend wird ein Zufallswert in drei verschiedenen Verteilungen generiert. Die rigged_dice
Verteilung einen Wert zwischen 0 und 5, erzeugt aber fast erzeugt immer ein 5
, weil die Chance ein generieren 5
ist 100 / 105
.