2 votes

L'utilisation de default_random_engine comme membre de la classe et sans classe donne des résultats différents (même graine).

Je veux avoir une classe séparée pour la génération de nombres aléatoires dans mon programme. J'ai essayé d'utiliser le std::default_random_engine comme membre de la classe et ensuite générer des vecteurs aléatoires avec des fonctions. Lorsque j'ai comparé les résultats à la génération de nombres aléatoires sans classe, j'ai remarqué que pour les dimensions inégales, un nombre aléatoire dans la séquence est sauté. Par exemple (bien sûr pas aléatoire) :

1,2,3 & 5,6,7 & 9,10,11 (sequence with class)
1,2,3 & 4,5,6 & 7, 8, 9 (sequence without class)

Pour les dimensions paires, les deux séquences sont les mêmes. J'ai donc essayé de faire un exemple de code pour illustrer les différences.

Dans cet exemple, j'ai également remarqué que, dans le cas de 4-dim, un nombre supplémentaire est échantillonné comme premier nombre (pour le cas sans classe). Si j'utilise une autre distribution, par exemple uniforme, il n'y avait pas une telle différence.

Quelqu'un a-t-il une idée de ce que je fais mal ? Est-ce que j'initialise trop souvent le générateur ?

J'apprécie toute aide.

Petit exemple de code :

#include <random>
#include <iostream>

class RandomGenerator{
  public:
    RandomGenerator(int seed):generator_(seed){}
    void generateGaussian(int dim){
      std::normal_distribution<double> distribution(0.,1.);
      for(int i=0; i<dim;++i){
        std::cout<<distribution(generator_)<<std::endl;
      }
    }
  private:
    std::default_random_engine generator_;
};

int main(){
  std::normal_distribution<double> distribution(0.,1.);

  std::cout<<std::endl<<"With Class - 4dim"<<std::endl;
  RandomGenerator random_generator4=RandomGenerator(912134);

  random_generator4.generateGaussian(4);
  std::cout<<"***"<<std::endl;
  random_generator4.generateGaussian(4);
  std::cout<<"***"<<std::endl;
  random_generator4.generateGaussian(4);

  std::cout<<std::endl<<"Without Class"<<std::endl;
  std::default_random_engine generator4(912134);
  for(int i=0; i<15;++i){
    std::cout<<distribution(generator4)<<std::endl;
    if((i+1)%4==0){
        std::cout<<"***"<<std::endl;
    }
  }

  std::default_random_engine generator(912134);
  RandomGenerator random_generator=RandomGenerator(912134);
  std::cout<<"With Class - 3dim "<<std::endl;
  random_generator.generateGaussian(3);
  std::cout<<"***"<<std::endl;
  random_generator.generateGaussian(3);
  std::cout<<"***"<<std::endl;
  random_generator.generateGaussian(3);

  std::cout<<std::endl<<"Without Class"<<std::endl;
  for(int i=0; i<11;++i){
    std::cout<<distribution(generator)<<std::endl;
    if((i+1)%3==0){
        std::cout<<"***"<<std::endl;
    }
  }
  return 0;
}

éditer : J'ai ajouté ceci au code. Maintenant les résultats sont exactement les mêmes. Je vais tester les propriétés statistiques pour vérifier si les résultats avec la réinitialisation sont toujours gaussiens.

if((i+1)%3==0){
    distribution.reset();
    std::cout<<"***"<<std::endl;
}

0voto

sascha Points 17084

Au moins dans C++11, les distributions pourraient avoir un état interne, tout comme les PRNGS. (J'ai observé que cet état est utilisé au moins pour la distribution normale ; peut-être que la distribution uniforme se comporte différemment).

Sans analyser votre code exactement (difficile à lire pour mon œil paresseux de programmeur python), je peux imaginer que c'est la source de ces observations.

Donc, quand vous commencez std::normal_distribution<double> distribution(0.,1.); à la première ligne dans votre main, cet objet sera utilisé dans les deux sans classe et la seconde ne repartira pas de zéro, car la première a modifié l'état interne (il ne suffit donc pas d'ensemencer votre PRNG).

Votre approche basée sur les classes a cependant une nouvelle distribution lorsqu'elle appelle generateGaussian .

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