Die Boost C++ Bibliotheken

Kapitel 60. Boost.Random

Die Bibliothek Boost.Random bietet zahlreiche Zufallsgeneratoren an, die es Ihnen erlauben zu wählen, auf welche Weise Zufallszahlen erzeugt werden sollen. In C++ konnten über die Funktion std::rand() aus der Headerdatei cstdlib auch bisher Zufallszahlen erzeugt werden. In diesem Fall hängt es jedoch von der Implementation der Standardbibliothek ab, auf welche Weise Zufallsfallen generiert werden.

Sie können auf alle Zufallsgeneratoren und sonstigen Klassen und Funktionen der Bibliothek Boost.Random zugreifen, indem Sie die Headerdatei boost/random.hpp einbinden.

Beachten Sie, dass große Teile der Bibliothek mit C++11 in die Standardbibliothek aufgenommen wurden. Unterstützt Ihre Entwicklungsumgebung C++11, können Sie die folgenden Beispielprogramme zu Boost.Random umschreiben, indem Sie auf die Headerdatei random und den Namensraum std zugreifen.

Beispiel 60.1. Pseudo-Zufallszahlen mit boost::random::mt19937
#include <boost/random.hpp>
#include <iostream>
#include <ctime>
#include <cstdint>

int main()
{
  std::time_t now = std::time(0);
  boost::random::mt19937 gen{static_cast<std::uint32_t>(now)};
  std::cout << gen() << '\n';
}

Im Beispiel 60.1 wird auf den Zufallsgenerator boost::random::mt19937 zugegriffen. Indem der Operator operator() aufgerufen wird, wird eine Zufallszahl generiert, die auf die Standardausgabe ausgegeben wird.

Die von boost::random::mt19937 generierten Zufallszahlen sind Ganzzahlen. Es hängt vom Zufallsgenerator ab, ob Ganz- oder Kommazahlen erzeugt werden. Alle Zufallsgeneratoren definieren einen Typ result_type, über den der Typ der Zufallszahlen erhalten werden kann. boost::random::mt19937::result_type ist auf boost::uint32_t gesetzt.

Alle Zufallsgeneratoren bieten außerdem zwei Methoden min() und max() an. Sie geben die kleinste und größte Zahl zurück, die von einem Zufallsgenerator erzeugt werden kann.

Fast alle von Boost.Random angebotenen Zufallsgeneratoren sind Pseudo-Zufallsgeneratoren. Pseudo-Zufallsgeneratoren erzeugen keine wirklich zufälligen Zahlen. Sie basieren auf Algorithmen, die scheinbar zufällige Zahlen erzeugen. boost::random::mt19937 ist einer der angebotenen Pseudo-Zufallsgeneratoren.

Pseudo-Zufallsgeneratoren müssen typischerweise initialisiert werden. Werden sie mit gleichen Zahlen initialisiert, generieren sie gleiche Zufallszahlen. So wird im Beispiel 60.1 der Rückgabewert von std::time() an den Konstruktor von boost::random::mt19937 übergeben. Auf diese Weise soll sichergestellt werden, dass ein wiederholter Aufruf des Programms zu unterschiedlichen Zeitpunkten nicht zur Ausgabe der immer gleichen Zufallszahl führt.

Pseudo-Zufallsgeneratoren sind für die meisten Anwendungsfälle gut genug. Auch std::rand() basiert auf einem Pseudo-Zufallsgenerator, der mit std::srand() initialisiert werden muss. Boost.Random bietet jedoch auch einen Zufallsgenerator an, der echte Zufallszahlen generieren kann – vorausgesetzt, ein Betriebssystem bietet eine Zufallsquelle an, die echte Zufallszahlen erzeugt.

Beispiel 60.2. Echte Zufallszahlen mit boost::random::random_device
#include <boost/random/random_device.hpp>
#include <iostream>

int main()
{
  boost::random::random_device gen;
  std::cout << gen() << '\n';
}

Boost.Random bietet mit boost::random::random_device einen nicht-deterministischen Zufallsgenerator an. Es handelt sich hierbei um einen Zufallsgenerator, der echte Zufallszahlen erzeugt. Es gibt keinen Algorithmus, der initialisiert werden muss und Zufallszahlen berechnet. Eine Vorhersage von Zufallszahlen ist demnach unmöglich. Nicht-deterministische Zufallsgeneratoren werden zum Beispiel in sicherheitsrelevanten Anwendungen verwendet.

boost::random::random_device greift zur Generierung von Zufallszahlen auf Betriebssystemfunktionen zu. Wird wie im Beispiel 60.2 der Standardkonstruktor verwendet, verwendet boost::random::random_device unter Windows den Kryptografiedienstanbieter MS_DEF_PROV und unter Linux den Gerätepfad /dev/urandom als Zufallsquelle.

Möchten Sie eine andere Zufallsquelle verwenden, greifen Sie auf den Konstruktor von boost::random::random_device zu, der einen Parameter vom Typ std::string erwartet. Es hängt vom Betriebssystem ab, wie dieser Parameter interpretiert wird. Unter Windows muss es der Name eines Kryptografiedienstanbieters sein, unter Linux ein Gerätepfad.

Beachten Sie, dass Sie die Headerdatei boost/random/random_device.hpp einbinden müssen, wenn Sie auf die Klasse boost::random::random_device zugreifen möchten. Diese Klasse ist nicht über boost/random.hpp verfügbar.

Beispiel 60.3. Die Zufallszahlen 0 oder 1 mit bernoulli_distribution
#include <boost/random.hpp>
#include <iostream>
#include <ctime>
#include <cstdint>

int main()
{
  std::time_t now = std::time(0);
  boost::random::mt19937 gen{static_cast<std::uint32_t>(now)};
  boost::random::bernoulli_distribution<> dist;
  std::cout << dist(gen) << '\n';
}

Im Beispiel 60.3 wird auf den Pseudo-Zufallsgenerator boost::random::mt19937 zugegriffen. Darüber hinaus kommt eine Distribution zum Einsatz. Als Distributionen bezeichnet Boost.Random Klassen, die die Bandbreite der Zufallszahlen eines Zufallsgenerators in eine andere Bandbreite übertragen. Während Zufallsgeneratoren wie boost::random::mt19937 eine eingebaute Unter- und Obergrenze für Zufallszahlen haben, die über min() und max() ermittelt werden kann, werden häufig Zufallszahlen innerhalb einer bestimmten Bandbreite benötigt.

Im Beispiel 60.3 soll der Wurf einer Münze simuliert werden. Da eine Münze nur zwei Seiten hat, soll der Zufallsgenerator 0 oder 1 zurückgeben. Eine Distribution, die nur eines von zwei Ergebnissen zurückgibt, ist boost::random::bernoulli_distribution.

Distributionen werden wie Zufallsgeneratoren verwendet: Sie rufen den Operator operator() auf, um eine Zufallszahl zu erhalten. Distributionen müssen Sie jedoch als Parameter einen Zufallsgenerator übergeben. Im Beispiel 60.3 verwendet dist den Zufallsgenerator gen, um 0 oder 1 zurückzugeben.

Beispiel 60.4. Zufallszahlen zwischen 1 und 100 mit uniform_int_distribution
#include <boost/random.hpp>
#include <iostream>
#include <ctime>
#include <cstdint>

int main()
{
  std::time_t now = std::time(0);
  boost::random::mt19937 gen{static_cast<std::uint32_t>(now)};
  boost::random::uniform_int_distribution<> dist{1, 100};
  std::cout << dist(gen) << '\n';
}

Boost.Random bietet zahlreiche Distributionen an. Im Beispiel 60.4 wird eine oft benötigte Distribution vorgestellt: Mit boost::random::uniform_int_distribution kann die Bandbreite der zu generierenden Zufallszahlen vorgegeben werden. So gibt dist im Beispiel 60.4 eine Zahl zwischen 1 und 100 zurück.

Beachten Sie, dass 1 und 100 ebenfalls gültige Zufallszahlen sind, die von dist zurückgegeben werden können. Distributionen werden mit einschließenden Unter- und Obergrenzen initialisiert.

Neben boost::random::bernoulli_distribution und boost::random::uniform_int_distribution können Sie auf zahlreiche weitere Distributionen in Boost.Random zugreifen. Dazu zählen zum Beispiel Distributionen wie boost::random::normal_distribution oder boost::random::chi_squared_distribution, wie sie in der Stochastik Verwendung finden.