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
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
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):
- 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)
- les nombres générés sont trop grossiers: vous pouvez obtenir 1/32768, 2/32768, 3/32768, mais jamais rien entre les deux.
- É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)
.
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;
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.
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.
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);
}