9 votes

C++ TR1 : comment utiliser la distribution normale ?

J'essaie d'utiliser le C++ STD TechnicalReport1 pour générer des nombres suivant une distribution normale, mais ce code (adapté de cet article ) :

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

n'imprime qu'un seul message de journal "Generating...", alors ne sort jamais de la boucle for ! Si j'utilise la distribution que j'ai commentée à la place, il se termine, donc je me demande ce que je fais de mal. Une idée ?

Merci beaucoup !

7voto

pmeerw Points 285

J'ai eu le même problème avec le code initialement posté et j'ai étudié l'implémentation GNU de

Tout d'abord, quelques observations : avec g++-4.4 et en utilisant le code se bloque, avec g++-4.5 et en utilisant -std=c++0x (c'est-à-dire pas TR1 mais la vraie chose) le code ci-dessus travaux

IMHO, il y a eu un changement entre TR1 et c++0x en ce qui concerne les adaptateurs entre la génération de nombres aléatoires et la consommation de nombres aléatoires -- mt19937 produit des entiers, normal_distribution consomme des doubles

le c++0x utilise l'adaptation automatiquement, le code g++ TR1 ne le fait pas.

pour que votre code fonctionne 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();

3voto

Jagannath Points 2326

Cela n'accrocherait certainement pas le programme. Mais, je ne suis pas sûr que cela réponde 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); 
 }

2voto

John D. Cook Points 19036

Si votre implémentation de la génération de nombres aléatoires TR1 est boguée, vous pouvez éviter TR1 en écrivant votre propre générateur normal 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. Ensuite, laissez r = sqrt( -2 log(u) ) et renvoyez x = r sin(2 pi v). (Cela s'appelle la méthode de Box-Mueller).

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

1voto

MSalters Points 74024

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X