2009-07-13 8 views
9

Je suis en train d'utiliser les C++ STD TechnicalReport1 extensions pour générer des nombres après une distribution normale, mais ce code (adapté de this article):C++ TR1: comment utiliser la distribution normale?

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; 
} 

imprime seulement 1 "Génération ..." message du journal , puis ne quitte jamais la boucle for! Si j'utilise la distribution, je la commente à la place, elle se termine, alors je me demande ce que je fais de mal. Une idée?

Merci beaucoup!

Répondre

2

Cela ne bloquerait certainement pas le programme. Mais, je ne sais pas si cela répond vraiment à vos besoins.

#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

merci l'homme, cela fonctionne comme un charme, mais je me demande pourquoi avec ce moteur cela fonctionne, et pas avec l'autre .. – puccio

+0

Évidemment, la seule différence est votre utilisation du mt19937 générateur de nombres alors que Jagannath utilise le std :: tr1 :: ranlux64_base_01. Logiquement, je suppose que le bug peut être dans votre implémentation de l'objet mt19937 (algo dont je n'avais jamais entendu parler avant vous, merci pour cela :-)) qui ne fait pas partie de std library. –

+0

Est-il possible de vectoriser une telle boucle pour dessiner des nombres aléatoires? Je rappelle que vous ne pouvez pas vectoriser une boucle qui a un appel de fonction. – Lindon

1

Bien que cela semble être un bug, une confirmation rapide serait de passer les paramètres par défaut 0.0, 1.0. normal_distribution<double>::normal_distribution() doit être égal à normal_distribution<double>::normal_distribution(0.0, 1.0)

+0

il ne fonctionne pas non plus , il reste encore bloqué en effectuant le premier calcul .. – puccio

2

Si votre TR1 mise en œuvre aléatoire de génération de nombres est bogué, vous pouvez éviter TR1 en écrivant votre propre générateur normale comme suit.

Générez deux échantillons aléatoires uniformes (0, 1) u et v en utilisant un générateur aléatoire de confiance. Soit r = sqrt (-2 log (u)) et renvoie x = r sin (2 pi v). (C'est ce qu'on appelle la méthode Box-Mueller.)

Si vous avez besoin d'échantillons d'échantillons normaux avec un μg moyen et un écart-type, renvoyez sigma * x + mu au lieu de simplement x.

+1

n'utilisez pas Box Muller. –

+0

Box Müller est lent – Lindon

+0

Juste essayé ceci. Il fonctionne super rapidement - testé avec des échantillons de 1M et il présente des stats presque parfaites pour des échantillons au sein de 1-sigma, 2-sigma, etc. –

7

J'ai eu le même problème avec le code initialement affiché et étudié la mise en œuvre GNU de

d'abord quelques observations: avec g ++ - 4.4 et en utilisant les blocages de code, avec g ++ - 4.5 et en utilisant std = C++ 0x (non TR1, mais la chose réelle) au-dessus du code fonctionne

à mon humble avis, il y avait un changement entre TR1 et C++ 0x ce qui concerne les adaptateurs entre génération de nombres aléatoires et la consommation de nombres aléatoires - mt19937 produit des entiers, normal_distribution consomme des doubles

C++ 0x utilise adaption automatiquement, le g ++ Code TR1 ne

afin d'obtenir votre code de travail avec g ++ - 4.4 et TR1, procédez comme suit

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(); 
Questions connexes