2009-07-13 11 views
9

Ich versuche, die C++ STD TechnicalReport1 Erweiterungen verwenden Nummern einer Normalverteilung zu erzeugen, aber dieser Code (angepasst von this article):C++ TR1: wie die normale_verteilung zu verwenden?

mt19937 eng; 
eng.seed(SEED); 

normal_distribution<double> dist; 
// XXX if I use the one below it exits the for loop 
// uniform_int<int> dist(1, 52); 

for (unsigned int i = 0; i < 1000; ++i) { 
    cout << "Generating " << i << "-th value" << endl; 
    cout << dist(eng) << endl; 
} 

druckt nur 1 „Erstellen ...“ Protokollmeldung , dann beendet nie die for-Schleife! Wenn ich die Distribution verwende, habe ich sie stattdessen auskommentiert, sie endet, also frage ich mich, was ich falsch mache. Irgendeine Idee?

Vielen Dank!

Antwort

2

Dies würde definitiv das Programm nicht hängen. Aber, nicht sicher, ob es wirklich Ihren Bedürfnissen entspricht.

#include <random> 
#include <iostream> 

using namespace std; 

typedef std::tr1::ranlux64_base_01 Myeng; 

typedef std::tr1::normal_distribution<double> Mydist; 

int main() 
{ 
     Myeng eng; 
     eng.seed(1000); 
     Mydist dist(1,10); 

     dist.reset(); // discard any cached values 
     for (int i = 0; i < 10; i++) 
     { 
      std::cout << "a random value == " << (int)dist(eng) << std::endl; 
     } 

return (0); 
} 
+0

Danke Mann, es funktioniert wie ein Charme, aber ich frage mich, warum mit dieser Maschine funktioniert, und nicht mit den anderen .. – puccio

+0

Offensichtlich ist der einzige Unterschied, dass Sie die verwenden mt19937 Zahlengenerator, während Jagannath die std :: tr1 :: ranlux64_base_01 verwendet. Logisch, ich vermute, dass der Fehler in Ihrer Implementierung des mt19937-Objekts (Algo, von dem ich noch nie zuvor gehört hatte, thx dafür :-)), die nicht Teil der Std-Bibliothek ist. –

+0

Kann man eine solche for-Schleife beim Zeichnen von Zufallszahlen vektorisieren? Ich erinnere mich, dass Sie eine Schleife, die einen Funktionsaufruf hat, nicht vektorisieren können. – Lindon

1

Während dies ein Fehler zu sein scheint, wäre eine schnelle Bestätigung, die Standardparameter 0.0, 1.0 zu übergeben. normal_distribution<double>::normal_distribution() sollte gleich normal_distribution<double>::normal_distribution(0.0, 1.0)

+0

es funktioniert auch nicht Es bleibt immer noch stecken die erste Berechnung .. – puccio

2

Wenn Ihre Implementierung der TR1-Zufallsgenerierung fehlerhaft ist, können Sie TR1 vermeiden, indem Sie wie folgt Ihren eigenen normalen Generator schreiben.

Generieren Sie zwei einheitliche (0, 1) Stichproben u und v mit einem beliebigen Zufallsgenerator, dem Sie vertrauen. Dann sei r = sqrt (-2 log (u)) und gebe x = r sin (2 pi v) zurück. (Dies wird als Box-Mueller-Methode bezeichnet.)

Wenn Sie normale Proben mit einem Mittelwert von μ und einer Standardabweichung benötigen, geben Sie sigma * x + mu anstelle von x zurück.

+1

Box Müller nicht verwenden. –

+0

Box Müller ist langsam – Lindon

+0

Probieren Sie es aus. Es läuft super schnell - getestet mit 1M Samples und es zeigte fast perfekte Werte für Samples innerhalb von 1-Sigma, 2-Sigma usw. –

7

Ich habe das gleiche Problem mit dem Code ursprünglich gebucht habe und untersuchte die GNU-Implementierung von

ersten einigen Beobachtungen: mit g ++ - 4.4 und unter Verwendung des Code hängt, mit g ++ - 4.5 und mit -std = C++ 0x (dh nicht TR1, sondern die reale Sache) über Code funktioniert

IMHO, gab es einen Wechsel zwischen TR1 und C++ 0x in Bezug auf Adapter zwischen Zufallsgenerierung und Verbrauch von Zufallszahlen - mt19937 erzeugt Ganzzahlen, normal_distribution verbraucht doubles

der C++ 0x verwendet Anpassung automatisch die g ++ TR1 Code nicht

um mit g arbeiten Sie Ihren Code zu erhalten ++ - 4.4 und TR1, gehen Sie wie folgt

std::tr1::mt19937 prng(seed); 
std::tr1::normal_distribution<double> normal; 
std::tr1::variate_generator<std::tr1::mt19937, std::tr1::normal_distribution<double> > randn(prng,normal); 
double r = randn();