HOWTO · C++

Wie man eine Random-Float-Zahl in C++ generiert

Dieser Artikel zeigt, wie man eine zufällige Gleitkommazahl in C++ generiert

Auf dieser Seite

Verwenden Sie die C++11-Bibliothek <random>, um einen pseudozufälligen Gleitkommawert in einem gewählten Bereich zu erzeugen. std::uniform_real_distribution übernimmt die untere und obere Grenze, während ein Zufallszahlengenerator die Zahlenfolge liefert. Wählen Sie je nach benötigter Genauigkeit Ihrer Anwendung float oder double; rand eignet sich nur zur Wartung von Legacy-Code.

Einen zufälligen Gleitkommawert mit C++11 erzeugen

Dieses vollständige Programm erzeugt fünf Werte im halboffenen Intervall [10, 100). Mit dem festen Startwert lässt sich die Zahlenfolge des Generators bei derselben Standardbibliotheksimplementierung wiederholen, was beim Debuggen hilfreich ist. Die ausgegebenen Werte können sich zwischen Implementierungen unterscheiden, da der Standard keine portabel identische Folge für den Verteilungsalgorithmus festlegt.

Führen Sie dieses Beispiel aus:

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

int main() {
  std::mt19937 engine(2026);
  std::uniform_real_distribution<double> distribution(10.0, 100.0);

  for (int i = 0; i < 5; ++i) {
    std::cout << std::setprecision(10) << distribution(engine) << '\n';
  }
}
78.99481399
96.50696843
96.65823206
73.63312607
11.77415091

Das Template-Argument der Verteilung legt den Ergebnistyp fest. Standardmäßig ist es double; der Standard unterstützt float, double und long double. Geben Sie den Typ explizit an, damit er beim Aufruf klar erkennbar ist: Das Beispiel verwendet double, während std::uniform_real_distribution<float> Werte vom Typ float anfordert. Die Grenzen sind reelle Werte; die Verteilung schließt die obere Grenze aus. Dieses halboffene Intervall ist nützlich, wenn Werte auf Bereiche skaliert werden, in denen ein exakter oberer Endpunkt mit dem nächsten Intervall überlappen würde. Ein Bereich von 0.0 bis 1.0 kann beispielsweise einen normierten Anteil darstellen, während ein Bereich von 10.0 bis 100.0 eine Messgröße in einer gewählten Einheit abbilden kann.

Verwenden Sie float, wenn dessen Genauigkeit ausreicht und Speicherplatz oder Bandbreite wichtig sind. double bietet in der Regel ein ausgewogenes Verhältnis zwischen Genauigkeit und Wertebereich. long double ist verfügbar, wenn zusätzliche Genauigkeit hilfreich ist; wie viel mehr Genauigkeit es bietet, hängt jedoch von der Implementierung ab. Stimmen Sie die Typen der Grenzwerte nach Möglichkeit auf den Verteilungstyp ab, besonders wenn Sie das Template-Argument ändern. So lässt sich der beabsichtigte Bereich leichter prüfen. Die Verteilung garantiert auch bei festem Startwert keine identische ausgegebene Zahlenfolge über verschiedene Standardbibliotheksimplementierungen hinweg.

Lassen Sie den Generator während der Erzeugung einer Folge bestehen und verwenden Sie ihn wieder. Wird für jeden Wert ein neu initialisierter Generator erstellt, kann sich die Folge wiederholen oder an Qualität verlieren. Für wiederholbare Ergebnisse verwenden Sie wie oben einen festen Startwert. Für eine andere Folge bei jedem Programmstart kann std::random_device Startwertmaterial liefern, sofern die Implementierung nichtdeterministische Ausgaben unterstützt; das ist nicht auf jedem System garantiert. Keine dieser Methoden macht diesen universell einsetzbaren Pseudozufallszahlengenerator für sicherheitsrelevante Werte geeignet. Ein Startwert initialisiert den Generator einmal; er bedeutet nicht, dass für jede Ziehung ein neuer unabhängiger Generator erstellt werden soll. Wenn eine Anwendung über mehrere Programmläufe hinweg reproduzierbare Ergebnisse benötigt, speichern Sie den Startwert zusammen mit den übrigen Eingaben. Für sicherheitsrelevante Tokens sollten Sie eine kryptografische Zufallsquelle statt dieser Verteilung und dieses Generators verwenden.

rand als eingeschränkte Legacy-Alternative verwenden

Die C-Bibliotheksfunktion rand() liefert eine pseudozufällige Ganzzahl von 0 bis einschließlich zum implementierungsabhängigen Wert RAND_MAX. Um sie auf einen Gleitkommabereich abzubilden, teilen Sie vor der Skalierung mit Gleitkommaarithmetik durch RAND_MAX. Dieses Beispiel bildet auf [10, 100] ab; der obere Endpunkt ist eingeschlossen, wenn rand() den Wert RAND_MAX liefert:

#include <cstdlib>
#include <iostream>

int main() {
  const double lower = 10.0;
  const double upper = 100.0;
  std::srand(2026);

  for (int i = 0; i < 5; ++i) {
    const double value = lower + (upper - lower) *
        (static_cast<double>(std::rand()) / RAND_MAX);
    std::cout << value << '\n';
  }
}
60.2772
88.4741
67.8989
11.5099
83.7273

rand() verfügt nur über einen begrenzten Zustand und eine eingeschränkte statistische Qualität. Ein fester Startwert macht dieses Beispiel bei derselben C-Bibliotheksimplementierung wiederholbar, aber weder unvorhersehbar noch sicher. Bevorzugen Sie für neuen C++-Code <random>, da diese Bibliothek Generator und Verteilung voneinander trennt und Typ sowie Wertebereich direkt festlegen lässt.