rand() entre 0 et 1

Donc le code suivant Fait 0

r = ((double) rand() / (RAND_MAX))

Pourquoi avoir r = ((double) rand() / (RAND_MAX + 1)) fait -1

L'ajout D'un à RAND_MAX ne devrait-il pas faire 1

Edit: je recevais un avertissement: débordement entier dans l'expression

Sur cette ligne, donc ça pourrait être le problème. Je viens de faire cout << r << endl et cela me donne définitivement des valeurs entre -1 et 0

56
demandé sur Rakete1111 2012-03-27 00:04:00

6 réponses

C'est tout à fait mise en œuvre spécifique, mais il semble que, dans l'environnement C++ vous travaillez, RAND_MAX est égal à INT_MAX.

Pour cette raison, RAND_MAX + 1 présente un comportement indéfini (débordement) et devient INT_MIN. Alors que votre instruction initiale se divisait (#aléatoire entre 0 et INT_MAX)/(INT_MAX) et générer une valeur 0 <= r < 1, maintenant il se divise (#aléatoire entre 0 et INT_MAX)/(INT_MIN), générer une valeur -1 < r <= 0

, afin de générer un nombre aléatoire 1 <= r < 2, vous voulez

r = ((double) rand() / (RAND_MAX)) + 1
64
répondu Sam DeHaan 2013-11-01 14:00:48

rand() / double(RAND_MAX) génère un nombre aléatoire à virgule flottante entre 0 (inclus) et 1 (inclus), mais ce n'est pas un bon moyen pour les raisons suivantes (car RAND_MAX est généralement 32767):

  1. Le nombre de nombres aléatoires qui peuvent être générés est trop petit: 32768. Si vous avez besoin de nombres aléatoires plus différents, vous avez besoin d'une manière différente (un exemple de code est donné ci-dessous)
  2. les nombres générés sont trop grossiers: vous pouvez obtenir 1/32768, 2/32768, 3/32768, mais jamais rien entre les deux.
  3. États limités du moteur générateur de nombres aléatoires: après avoir généré des nombres aléatoires RAND_MAX, les implémentations commencent généralement à répéter la même séquence de nombres aléatoires.

En raison des limitations ci-dessus de rand (), un meilleur choix pour la génération de nombres aléatoires entre 0 (inclus) et 1 ( exclusif ) serait l'extrait suivant (similaire à l'exemple à http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution ):

#include <iostream>
#include <random>
#include <chrono>

int main()
{
    std::mt19937_64 rng;
    // initialize the random number generator with time-dependent seed
    uint64_t timeSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
    std::seed_seq ss{uint32_t(timeSeed & 0xffffffff), uint32_t(timeSeed>>32)};
    rng.seed(ss);
    // initialize a uniform distribution between 0 and 1
    std::uniform_real_distribution<double> unif(0, 1);
    // ready to generate random numbers
    const int nSimulations = 10;
    for (int i = 0; i < nSimulations; i++)
    {
        double currentRandomNumber = unif(rng);
        std::cout << currentRandomNumber << std::endl;
    }
    return 0;
}

Ceci est facile à modifier pour générer des nombres aléatoires entre 1 (inclus) et 2 (exclusif) en remplaçant unif(0, 1) par unif(1, 2).

18
répondu Serge Rogatch 2015-06-27 17:26:58

Non, car RAND_MAX est généralement étendu à MAX_INT. Donc, en ajoutant un (apparemment) le met à MIN_INT (bien qu'il devrait être un comportement indéfini comme on me le dit), d'où l'inversion du signe.

Pour obtenir ce que vous voulez, vous devrez déplacer le + 1 en dehors du calcul:

r = ((double) rand() / (RAND_MAX)) + 1;
15
répondu Tudor 2012-03-26 20:12:34

Ce n'est pas le cas. il fait 0 <= r < 1, mais votre original est 0 <= r <= 1.

Notez que cela peut conduire à comportement indéfini si RAND_MAX + 1 débordements.

3
répondu Luchian Grigore 2012-03-26 20:07:20

Je suppose que RAND_MAX est égal à INT_MAX et donc vous êtes débordant à un négatif.

Faites simplement ceci:

r = ((double) rand() / (RAND_MAX)) + 1;

Ou mieux encore, utilisez les générateurs de nombres aléatoires de C++11.

2
répondu Pubby 2012-03-26 20:21:40

C'est la bonne façon:

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

Ou

double randd() {
  return (double)rand() / (RAND_MAX + 1.0);
}
1
répondu KIM Taegyoon 2015-04-04 05:57:19