308 votes

Génération de nombres aléatoires flotteur C++

Comment générer des flotteurs aléatoires en C++ ?

J’ai pensé que je pouvais prendre l’entier rand et divisez-la par quelque chose, serait-ce suffisant ?

431voto

John Dibling Points 56814

rand() peut être utilisé pour générer psudo-les nombres aléatoires en C++. En combinaison avec d' RAND_MAX et un peu de mathématiques, vous pouvez générer des nombres aléatoires dans n'importe quel intervalle que vous choisissez. Cela est suffisant pour des fins d'apprentissage et de jouets programmes. Si vous avez besoin vraiment de nombres aléatoires avec une distribution normale, vous aurez besoin d'employer une méthode plus avancée.


Cela va générer un certain nombre de 0.0 à 1.0 inclus.

float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);

Cela va générer un certain nombre de 0,0 à certains arbitraire float, X:

float r2 = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX/X));

Cela va générer un certain nombre d'arbitraire LO d'arbitraire HI:

float r3 = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));

Notez que l' rand() fonction souvent de ne pas être suffisant si vous avez besoin de nombres réellement aléatoires.


Avant d'appeler, rand(), vous devez d'abord "de la" graine du générateur de nombres aléatoires en appelant srand(). Cela devrait être fait une fois au cours de votre programme à exécuter -- pas une seule fois chaque fois que vous appelez rand(). C'est souvent comme cela:

srand (static_cast <unsigned> (time(0)));

Pour appeler l' rand ou srand vous devez #include <cstdlib>.

Pour appeler l' time, vous devez d' #include <ctime>.

164voto

Shafik Yaghmour Points 42198

C++11 vous donne beaucoup de nouvelles options avec random.

Pour voir pourquoi l'utilisation d' rand() peut être problématique voir le rand() Considérés comme Nocifs du matériel de présentation par Stephan T. Lavavej donné au cours de la GoingNative 2013 de l'événement. Les diapositives sont dans les commentaires, mais voici un lien direct.

L'exemple ci-dessous est distillée à partir du document ci-dessus et utilise des std::mersenne_twister_engine moteur et le std::uniform_real_distribution qui génère des nombres dans l' [0,10) intervalle, avec d'autres moteurs et les distributions en commentaire (voir en direct):

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>

int main()
{
    std::random_device rd;

    //
    // Engines 
    //
    std::mt19937 e2(rd());
    //std::knuth_b e2(rd());
    //std::default_random_engine e2(rd()) ;

    //
    // Distribtuions
    //
    std::uniform_real_distribution<> dist(0, 10);
    //std::normal_distribution<> dist(2, 2);
    //std::student_t_distribution<> dist(5);
    //std::poisson_distribution<> dist(2);
    //std::extreme_value_distribution<> dist(0,2);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::floor(dist(e2))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

la sortie sera semblable au suivant:

0 ****
1 ****
2 ****
3 ****
4 *****
5 ****
6 *****
7 ****
8 *****
9 ****

La sortie varie selon la distribution que vous choisissez, donc si nous avons décidé d'aller avec std::normal_distribution<> dist(2, 2); au lieu de std::uniform_real_distribution<> dist(0, 10); le résultat serait similaire à ceci:

-6 
-5 
-4 
-3 
-2 **
-1 ****
 0 *******
 1 *********
 2 *********
 3 *******
 4 ****
 5 **
 6 
 7 
 8 
 9 

Boost

Bien sûr Boost.Aléatoire est toujours une option, ici j'utilise boost::random::uniform_real_distribution:

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>

int main()
{
    boost::random::mt19937 gen;
    boost::random::uniform_real_distribution<> dist(0, 10);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::floor(dist(gen))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

rand()

Si vous devez utiliser rand() alors nous pouvons aller à la C FAQ pour une, des guides sur Comment puis-je générer à virgule flottante nombres aléatoires? , qui, fondamentalement, donne un exemple similaire à ce pour la génération d'un sur l'intervalle [0,1):

#include <stdlib.h>

double randZeroToOne()
{
    return rand() / (RAND_MAX + 1.);
}

et pour générer un nombre aléatoire dans l'intervalle de [M,N):

double randMToN(double M, double N)
{
    return M + (rand() / ( RAND_MAX / (N-M) ) ) ;  
}

68voto

rlbond Points 24215

Jetez un oeil à Boost.Random. Vous pourriez faire quelque chose comme ceci :

Jouez, vous pourriez faire mieux en passant l’objet même de mt19937 entier au lieu de construire une nouvelle chaque fois, mais j’espère que vous avez l’idée.

34voto

ГошУ Points 6799

appelez le code avec deux valeurs flottantes, le code fonctionne dans n'importe quelle plage.

 float rand_FloatRange(float a, float b)
{
return ((b-a)*((float)rand()/RAND_MAX))+a;
}
 

22voto

Rick Points 2477

Si vous êtes à l'aide de C++ et pas en C, puis n'oubliez pas que dans le rapport technique 1 (TR1) et dans le C++0x projet, ils ont ajouté des installations pour un générateur de nombre aléatoire dans le fichier d'en-tête, je crois que c'est identique pour le coup de pouce.Bibliothèque aléatoire et certainement plus souple et plus "moderne" que la fonction de la bibliothèque C, rand.

Cette syntaxe offre la possibilité de choisir un générateur (comme le mersenne twister mt19937) et ensuite choisir une distribution (normal, bernoulli, binomiale, etc.).

La syntaxe est comme suit (sans vergogne emprunté à partir de ce site):

  #include <iostream>
  #include <random>

  ...

  std::tr1::mt19937 eng;  // a core engine class 
  std::tr1::normal_distribution<float> dist;     

  for (int i = 0; i < 10; ++i)        
      std::cout << dist(eng) << std::endl;

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