78 votes

rand() entre 0 et 1

Donc le code suivant fait 0 < r < 1

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

Pourquoi le fait d'avoir r = ((double) rand() / (RAND_MAX + 1)) faire -1 < r < 0 ?

Le fait d'ajouter un à RAND_MAX ne devrait-il pas rendre 1 < r < 2 ?

Edit : Je recevais un avertissement : dépassement d'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

2 votes

Essayez d'ajouter 1 après le dernier )

15 votes

Notez que vous devez utiliser distribution_réelle_uniforme de toute façon pour ça. Si vous n'avez pas C++11, utilisez la fonction version améliorée .

0 votes

Erreur d'algèbre. Si r est un nombre aléatoire dans l'intervalle de zéro à m alors le rapport r/m sera dans l'intervalle (0,1) pero r/(m+1) sera dans l'intervalle (0, m/(m+1)) PAS la gamme (1,2) . Si m est très grand (par rapport à un), alors m/(m+1) est approximativement égal à un, donc votre expression r = ((double) rand() / (RAND_MAX + 1)) donnerait un nombre aléatoire approximativement dans l'intervalle (0,1) - c'est-à-dire, s'il n'y avait pas de débordement.

94voto

Sam DeHaan Points 7096

C'est entièrement spécifique à la mise en œuvre mais il semble que dans l'environnement C++ dans lequel vous travaillez, RAND_MAX est égal à INT_MAX .

A cause de ça, RAND_MAX + 1 présente un comportement non défini (débordement) et devient INT_MIN . Alors que votre déclaration initiale divisait (# aléatoire entre 0 et INT_MAX )/( INT_MAX ) et de générer une valeur 0 <= r < 1 maintenant, il divise (# aléatoire entre 0 et INT_MAX )/( INT_MIN ), générant une valeur -1 < r <= 0

Afin de générer un nombre aléatoire 1 <= r < 2 vous voudriez

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

40voto

Serge Rogatch Points 18

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

  1. Le nombre de numéros aléatoires différents qui peuvent être générés est trop faible : 32768. Si vous avez besoin de plus de nombres aléatoires différents, vous devez utiliser une autre méthode (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 d'intermédiaire.
  3. États limités du moteur du 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 de rand() mentionnées ci-dessus, un meilleur choix pour la génération de nombres aléatoires entre 0 (inclus) et 1 ( exclusif ) serait le code suivant (similaire à l'exemple de l'adresse suivante 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;
}

Il est facile de le modifier pour générer des nombres aléatoires entre 1 (inclus) et 2 (exclus) en remplaçant unif(0, 1) con unif(1, 2) .

18voto

Tudor Points 39539

Non, car RAND_MAX est généralement étendu à MAX_INT. Donc en ajouter un (apparemment) le met à MIN_INT (bien que cela doive être un comportement non défini d'après ce qu'on m'a 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;

2 votes

Ajout d'un mai le mettre à MIN_INT, mais c'est toujours UB.

2 votes

En ajouter un conduit à un comportement non défini, car tous les débordements. C'est faux et trompeur, car cela semble fonctionner. Corrigez votre réponse ou supprimez-la.

0 votes

Je suis d'accord, j'ai modifié en conséquence. Cela semble toutefois être le comportement observé.

3voto

KIM Taegyoon Points 196

C'est le bon chemin :

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

o

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

3voto

Luchian Grigore Points 136646

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éborde.

1 votes

RAND_MAX ne peut pas dépasser un type non signé, vous pouvez donc le convertir en non signé.

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