2013-07-22 2 views
6

Ich war überrascht, dass die Ausgabe dieses Programms:Wie viele Zufallszahlen verwendet std :: uniform_real_distribution?

#include <iostream> 
#include <random> 

int main() 
{ 
    std::mt19937 rng1; 
    std::mt19937 rng2; 
    std::uniform_real_distribution<double> dist; 

    double random = dist(rng1); 
    rng2.discard(2); 

    std::cout << (rng1() - rng2()) << "\n"; 

    return 0; 
} 

ist 0 - d.h. std::uniform_real_distribution zwei Zufallszahl verwendet einen Zufall double Wert im Bereich [0,1) zu erzeugen. Ich dachte, es würde nur einen generieren und das skalieren. Nachdem ich darüber nachgedacht habe, denke ich, dass dies daran liegt, dass std::mt19937 32-Bit-Ints erzeugt und Double ist doppelt so groß und daher nicht "zufällig genug".

Frage: Wie finde ich diese Zahl generisch, d. H. Wenn der Zufallszahlengenerator und der Fließkommatyp beliebige Typen sind?

Edit: Mir ist gerade aufgefallen, dass ich stattdessen std::generate_canonical verwenden konnte, da ich nur an Zufallszahlen von [0,1] interessiert bin. Nicht sicher, ob dies einen Unterschied macht.

+0

Sie können dies nicht allgemein finden. –

+2

@ R.MartinhoFernandes: weil ... – arne

+1

Denken Sie darüber nach, was es bedeuten würde, eine 32-Bit-Ganzzahl zu einem 64-Bit-Doppelbild zu "rescale": Es gibt ungefähr 2^62 verschiedene Doppelwerte. Es gibt 2^32 verschiedene int-Werte. Dies bedeutet, dass nur ** eine von jeder Milliarde ** möglichen doppelten Werten in dem resultierenden Doppel darstellbar wäre. Dies ist eindeutig inakzeptabel. – JohannesD

Antwort

2

template<class RealType, size_t bits, class URNG> std::generate_canonical Für die Norm (Abschnitt 27.5.7.2) definiert explizit die Anzahl der Anrufe an den einheitlichen Zufallszahlengenerator (URNG)

max (1, b/log_2 R) zu sein,

wo b ist das Minimum der Anzahl der Bits in der Mantisse des RealType und der Anzahl der Bits, die an generate_canonical als Template-Parameter übergeben werden. R ist der Zahlenbereich, den der URNG zurückgeben kann (URNG::max()-URNG::min()+1). In Ihrem Beispiel wird dies jedoch keinen Unterschied machen, da Sie zum mt19937 2 Aufrufe benötigen, um die 53 Bits der Mantisse des Double zu füllen.

Für andere Distributionen bietet der Standard keine allgemeine Möglichkeit, Informationen darüber zu erhalten, wie viele Nummern das URNG generieren muss, um eine Nummer der Verteilung zu erhalten.

Ein Grund könnte sein, dass für einige Distributionen die Anzahl einheitlicher Zufallszahlen, die zum Generieren einer einzigen Nummer der Verteilung erforderlich sind, nicht festgelegt ist und von Aufruf zu Aufruf variieren kann. Ein Beispiel ist das std::poisson_distribution, das üblicherweise als eine Schleife implementiert ist, die in jeder Iteration eine einheitliche Zufallszahl zeichnet, bis das Produkt dieser Zahlen einen bestimmten Schwellenwert erreicht hat (siehe beispielsweise implementation of the GNU C++ library (Zeile 1523-1528)).

Verwandte Themen