Question

Le code suivant fournit en sortie un nombre aléatoire à chaque seconde:

int main ()
{
    srand(time(NULL)); // Seeds number generator with execution time.

    while (true)
    {
        int rawRand = rand();

        std::cout << rawRand << std::endl;

        sleep(1);
    }
}

Comment pourrais-je dimensionner ces chiffres vers le bas de sorte qu'ils sont toujours dans la gamme de 0-100?

Était-ce utile?

La solution

Si vous utilisez C ++ et sont préoccupés par une bonne distribution, vous pouvez utiliser TR1 C ++ 11 <random>.

#include <random>

std::random_device rseed;
std::mt19937 rgen(rseed()); // mersenne_twister
std::uniform_int_distribution<int> idist(0,100); // [0,100]

std::cout << idist(rgen) << std::endl;

Autres conseils

Tous les exemples affiché alors donnez loin effectivement des résultats mal distribués. Exécutez le code souvent et créer une statistique pour voir comment les valeurs deviennent biaisés.

Une meilleure façon de générer un réel uniforme distribution de nombre aléatoire dans tout intervalle [0, N ] est la suivante (en supposant que rand suit en fait une distribution uniforme, ce qui est loin d'être évident):

unsigned result;
do {
    result = rand();
} while (result > N);

Bien sûr, cette méthode est lente mais ne produire une bonne distribution. Une façon un peu plus intelligent de le faire est de trouver le plus grand multiple de N qui est plus petit que RAND_MAX et en utilisant que la borne supérieure. Après cela, on peut en toute sécurité prendre la result % (N + 1).

Pour une explication pourquoi la méthode de module naïf est mauvais et pourquoi ce qui précède est mieux, se référer à l'excellent article de Julienne sur en utilisant rand .

int rawRand = rand() % 101;

Voir (pour plus de détails):

rand - C ++ Référence

D'autres ont également souligné que cela ne va pas vous donner la meilleure distribution des nombres aléatoires possibles. Si ce genre de chose est important dans votre code, vous devez faire:

int rawRand = (rand() * 1.0 / RAND_MAX) * 100;

EDIT

Trois ans après, je fais une édition. Comme d'autres ont mentionné, rand() a beaucoup de questions. De toute évidence, je ne peux pas recommander son utilisation quand il existe de meilleures alternatives à l'avenir. Vous pouvez lire tous les détails et recommandations ici:

rand () Considered Harmful | GoingNative 2013

Vous pouvez faire

cout << rawRand % 100 << endl; // Outputs between 0 and 99

cout << rawRand % 101 << endl; // outputs between 0 and 100

Pour les personnes downvoting; noter une minute après ce que j'était à l'origine posté a laissé le commentaire:

  

De http://www.cplusplus.com/reference/clibrary/cstdlib/rand « Avis bien que cette opération modulo ne génère pas un nombre aléatoire vraiment uniformément réparti dans la durée (puisque dans la plupart des cas nombres inférieurs sont un peu plus probable), mais il est généralement une bonne approximation pour de courtes durées. »

ints 64 bits et en utilisant 100 nombres en tant que sortie, les numéros 0-16 sont représentés avec 1,00000000000000000455% du nombre (une précision par rapport à l'identique distribué de 1% d'environ 10 -18 ), tandis que les numéros 17-99 sont représentés avec 0,99999999999999999913% des numéros. Oui, pas parfaitement distribués, mais une très bonne approximation pour les petites portées.

A noter également, où est l'OP demander des numéros distribués de manière identique? Pour tout ce que nous savons que ce sont utilisés à des fins où un petit écart n'a pas d'importance (par exemple, autre chose que la cryptographie - et si elles utilisent les chiffres pour la cryptographie à cette question est beaucoup trop naïve pour eux d'écrire leur propre cryptographie ).

EDIT - Pour les personnes qui sont vraiment soucié d'avoir une distribution uniforme de nombres aléatoires les travaux de code suivant. Notez que ce n'est pas nécessairement optimale comme 64 bits ints au hasard, il faudra deux appels de rand() une fois tous les 10 ^ 18 appels.

unsigned N = 100; // want numbers 0-99
unsigned long randTruncation = (RAND_MAX / N) * N; 
// include every number the N times by ensuring rawRand is between 0 and randTruncation - 1 or regenerate.
unsigned long rawRand = rand();

while (rawRand >= randTruncation) {
    rawRand = rand();  
// with 64-bit int and range of 0-99 will need to generate two random numbers
// about 1 in every (2^63)/16 ~ 10^18 times (1 million million times)

// with 32-bit int and range of 0-99 will need to generate two random numbers 
// once every 46 million times.

}
cout << rawRand % N << stdl::endl;

Voir man 3 rand -. Vous avez besoin à l'échelle en divisant par RAND_MAX pour obtenir l'intervalle [0, 1], après quoi vous pouvez multiplier par 100 pour votre fourchette cible

Pour la gamme min max (inclus), utilisation: int result = rand() % (max - min + 1) + min;

Combien de temps une réponse voulez-vous que.

est la plus simple à convertir en utilisant le reste lorsqu'il est divisé par 101:

int value = rawRand % 101;

A semipurist serait rééchelonner en utilisant doubles:

double dbl = 100 * ((double)rawRand / RAND_MAX);
int ivalue = (int)(dbl + 0.5);   // round up for above 0.5

Et les puristes dire que rand ne produit pas de nombres aléatoires.

Pour votre information, la qualité des nombres aléatoires est mesurée en prenant une séquence de nombres, puis en calculant la probabilité mathématique que la source de cette séquence était aléatoire. Simple bidouille en utilisant le reste est un très mauvais choix si vous êtes après aléatoire.

Certaines personnes ont posté le code suivant comme exemple:

int rawRand = (rand() / RAND_MAX) * 100;

Ceci est un moyen invalide de résoudre le problème, à la fois rand () et RAND_MAX sont des nombres entiers. En C ++, il en résulte la division intégrale, qui tronque les résultats décimaux points. Comme RAND_MAX> = rand (), le résultat de cette opération est 1 ou 0, ce qui signifie rawRand ne peut être que 0 ou 100. Une bonne façon de le faire serait la suivante:

int rawRand = (rand() / static_cast<double>(RAND_MAX)) * 100;

Depuis une opérandes est maintenant une double division à virgule flottante est utilisé, ce qui reviendrait une valeur appropriée entre 0 et 1.

rawRand% 101 donnerait [0-100], y compris.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top