88 votes

générer des nombres doubles aléatoires en c++

Comment générer des nombres aléatoires entre deux doubles en c++ , ces nombres devraient ressembler à xxxxx,yyyyy .

6 votes

"ces numéros devraient ressembler à xxxxx,yyyyy". La façon de générer des doubles aléatoires et la façon de formater les doubles en tant que chaînes de caractères sont des questions complètement distinctes.

0 votes

Et en y réfléchissant bien, on peut aussi envisager de générer une distribution uniforme doubles et en générant des données uniformément réparties décimales sont des tâches quelque peu différentes, bien que liées.

0 votes

La génération de nombres entiers uniformément distribués est plus étroitement liée au problème des décimales.

120voto

rep_movsd Points 2526

Voici comment

double fRand(double fMin, double fMax)
{
    double f = (double)rand() / RAND_MAX;
    return fMin + f * (fMax - fMin);
}

N'oubliez pas d'appeler srand() avec une graine appropriée à chaque fois que votre programme démarre.

[Edit] Cette réponse est obsolète depuis que le C++ a sa bibliothèque aléatoire native non basée sur le C (voir la réponse d'Alessandro Jacopson). Mais, ceci s'applique toujours au C

10 votes

Si vous ajoutez 1 à RAND_MAX, faites-le avec précaution, car il pourrait être égal à INT_MAX. double f = rand() / (RAND_MAX + 1.0);

8 votes

Notez que le caractère aléatoire peut être limité. La plage xxxxx,yyyyy suggère 10 chiffres décimaux. Il existe de nombreux systèmes où RAND_MAX est inférieur à 10^10. Cela signifierait que certains nombres dans cette plage ont p(xxxxx,yyyyy)==0.0

7 votes

Vous devez éviter rand() si possible. Voir l'autre réponse pour une solution C++11 ou TR1.

113voto

uvts_cvs Points 4163

Cette solution nécessite C++11 (ou TR1).

#include <random>

int main()
{
   double lower_bound = 0;
   double upper_bound = 10000;
   std::uniform_real_distribution<double> unif(lower_bound,upper_bound);
   std::default_random_engine re;
   double a_random_double = unif(re);

   return 0;
}

Pour plus de détails, voir l'article de John D. Cook. "Génération de nombres aléatoires à l'aide de C++ TR1" .

Voir également l'article de Stroustrup "Génération de nombres aléatoires" .

8 votes

Vous pourriez vouloir mettre à jour ce document avec une version plus récente. Référence cpp ce qui est plutôt bien.

7voto

Pixelchemist Points 3636

Si la précision est un problème ici, vous pouvez créer des nombres aléatoires avec une graduation plus fine en randomisant les bits significatifs. Supposons que nous voulions avoir un double entre 0,0 et 1000,0.

Sur MSVC (12 / Win32) RAND_MAX est 32767 par exemple.

Si vous utilisez la méthode commune rand()/RAND_MAX schéma vos écarts seront aussi grands que

1.0 / 32767.0 * ( 1000.0 - 0.0) = 0.0305 ...

Dans le cas des variables doubles IEE 754 (53 bits significatifs) et de la randomisation sur 53 bits, le plus petit écart de randomisation possible pour le problème 0 à 1000 sera de

2^-53 * (1000.0 - 0.0) = 1.110e-13

et donc nettement plus faible.

L'inconvénient est que 4 appels à rand() seront nécessaires pour obtenir le nombre intégral randomisé (en supposant un RNG de 15 bits).

double random_range (double const range_min, double const range_max)
{
  static unsigned long long const mant_mask53(9007199254740991);
  static double const i_to_d53(1.0/9007199254740992.0);
  unsigned long long const r( (unsigned long long(rand()) | (unsigned long long(rand()) << 15) | (unsigned long long(rand()) << 30) | (unsigned long long(rand()) << 45)) & mant_mask53 );
  return range_min + i_to_d53*double(r)*(range_max-range_min);
}

Si le nombre de bits pour la mantisse ou le RNG est inconnu, les valeurs respectives doivent être obtenues dans la fonction.

#include <limits>
using namespace std;
double random_range_p (double const range_min, double const range_max)
{
  static unsigned long long const num_mant_bits(numeric_limits<double>::digits), ll_one(1), 
    mant_limit(ll_one << num_mant_bits);
  static double const i_to_d(1.0/double(mant_limit));
  static size_t num_rand_calls, rng_bits;
  if (num_rand_calls == 0 || rng_bits == 0)
  {
    size_t const rand_max(RAND_MAX), one(1);
    while (rand_max > (one << rng_bits))
    {
      ++rng_bits;
    }
    num_rand_calls = size_t(ceil(double(num_mant_bits)/double(rng_bits)));
  }
  unsigned long long r(0);
  for (size_t i=0; i<num_rand_calls; ++i)
  {
    r |= (unsigned long long(rand()) << (i*rng_bits));
  }
  r = r & (mant_limit-ll_one);
  return range_min + i_to_d*double(r)*(range_max-range_min);
}

Note : Je ne sais pas si le nombre de bits pour les longs non signés (64 bits) est supérieur au nombre de bits de la double mantisse (53 bits pour IEE 754) sur toutes les plateformes ou non. Il serait probablement "intelligent" d'inclure une vérification du type if (sizeof(unsigned long long)*8 > num_mant_bits) ... si ce n'est pas le cas.

3voto

uvts_cvs Points 4163

Cet extrait est tiré directement de l'article de Stroustrup. Le langage de programmation C++ (4e édition) , §40.7 ; il nécessite C++11 :

#include <functional>
#include <random>

class Rand_double
{
public:
    Rand_double(double low, double high)
    :r(std::bind(std::uniform_real_distribution<>(low,high),std::default_random_engine())){}

    double operator()(){ return r(); }

private:
    std::function<double()> r;
};

#include <iostream>    
int main() {
    // create the random number generator:
    Rand_double rd{0,0.5};

    // print 10 random number between 0 and 0.5
    for (int i=0;i<10;++i){
        std::cout << rd() << ' ';
    }
    return 0;
}

0voto

Oleg Razgulyaev Points 2140

Quelque chose comme ça :

#include <iostream>
#include <time.h>

using namespace std;

int main()
{
    const long max_rand = 1000000L;
    double x1 = 12.33, x2 = 34.123, x;

    srandom(time(NULL));

    x = x1 + ( x2 - x1) * (random() % max_rand) / max_rand;

    cout << x1 << " <= " << x << " <= " << x2 << endl;

    return 0;
}

2 votes

"(random() % max_rand)" = "random()" (c'est-à-dire 3 % 7 = 3). Ce serait une étape de traitement perdue.

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