web-dev-qa-db-fra.com

rand () entre et 1

Donc le code suivant fait 0 <r <1 

r = ((double) Rand() / (Rand_MAX))

Pourquoi avoir r = ((double) Rand() / (Rand_MAX + 1)) make -1 <r <0?

En ajouter un à Rand_MAX ne devrait-il pas faire 1 <r <2?

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

sur cette ligne, alors que pourrait être le problème. Je viens de faire cout << r << endl et cela me donne des valeurs comprises entre -1 et 0

62
CyberShot

Ceci est entièrement spécifique à l'implémentation , mais il apparaît que dans l'environnement C++ dans lequel vous travaillez, Rand_MAX est égal à INT_MAX.

De ce fait, Rand_MAX + 1 présente un comportement non défini (débordement) et devient INT_MIN. Alors que votre déclaration initiale divisait (nombre aléatoire entre 0 et INT_MAX)/(INT_MAX) et générait une valeur 0 <= r < 1, elle divise maintenant (nombre 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
70
Sam DeHaan

Rand() / double(Rand_MAX) génère un nombre aléatoire à virgule flottante compris entre 0 (inclus) et 1 (inclusif), 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 différents pouvant être générés est trop petit: 32768. Si vous avez besoin de plus de nombres aléatoires différents, vous avez besoin d'une méthode 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 de génération 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 () ci-dessus, un meilleur choix pour la génération de nombres aléatoires compris entre 0 (inclus) et 1 (exclusive) serait le fragment suivant (similaire à l'exemple de 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 compris entre 1 (inclus) et 2 (exclusif) en remplaçant unif(0, 1) par unif(1, 2).

20
Serge Rogatch

Non, car Rand_MAX est généralement étendu à MAX_INT. Donc, en ajouter un (apparemment) le met à MIN_INT (bien que ce soit un comportement indéfini comme on me dit), d’où le renversement du signe.

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

r = ((double) Rand() / (Rand_MAX)) + 1;
16
Tudor

Ce n'est pas. Cela donne 0 <= r < 1, mais votre original est 0 <= r <= 1.

Notez que cela peut conduire à un comportement non défini si Rand_MAX + 1 déborde.

3
Luchian Grigore

Je suppose que Rand_MAX est égal à INT_MAX et que vous le débordez de manière négative.

Faites juste ceci:

r = ((double) Rand() / (Rand_MAX)) + 1;

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

2
Pubby

C'est le bon chemin:

double randd() {
  return (double)Rand() / ((double)Rand_MAX + 1);
}

ou

double randd() {
  return (double)Rand() / (Rand_MAX + 1.0);
}
1
KIM Taegyoon

Dans mon cas (j'utilise VS 2017) fonctionne bien avec le code simple suivant:

#include "pch.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>

int main()
{
    srand(time(NULL));

    for (int i = 1000; i > 0; i--) //try it thousand times
    {
        int randnum = (double)Rand() / ((double)Rand_MAX + 1);
        std::cout << " rnum: " << Rand()%2 ;
    }
} 
0
SeveneduS