web-dev-qa-db-fra.com

Comment puis-je obtenir une plage spécifique de nombres de Rand ()?

srand(time(null));

printf("%d", Rand());

Donne un nombre aléatoire haut de gamme (0-32000ish), mais il me faut seulement environ 0-63 ou 0-127, bien que je ne sois pas sûr de la façon de procéder. De l'aide?

32
akway
Rand() % (max_number + 1 - minimum_number) + minimum_number

Donc, pour les 0 à 65 ans:

Rand() % (65 + 1 - 0) + 0

(évidemment vous pouvez laisser le 0 éteint, mais c'est là pour être complet).

Notez que cela va légèrement biaiser le caractère aléatoire, mais ne vous inquiétez probablement pas si vous ne faites pas quelque chose de particulièrement sensible.

53
Tyler McHenry

vérifier ici

http://c-faq.com/lib/randrange.html

Pour l’une ou l’autre de ces techniques, il est facile de modifier la plage, si nécessaire; des nombres compris entre [M, N] pourraient être générés avec quelque chose comme

M + Rand() / (Rand_MAX / (N - M + 1) + 1)
16
fnurglewitz

En prenant le modulo du résultat, comme l’affirment les autres afficheurs, vous obtiendrez quelque chose de presque aléatoire, mais pas parfaitement.

Considérons cet exemple extrême, supposons que vous vouliez simuler un tirage au sort, en retournant 0 ou 1. Vous pouvez le faire:

isHeads = ( Rand() % 2 ) == 1;

Cela semble assez inoffensif, non? Supposons que Rand_MAX n’est que 3. C’est beaucoup plus élevé bien sûr, mais le fait est qu’il ya un biais lorsque vous utilisez un module qui ne divise pas uniformément Rand_MAX. Si vous voulez des nombres aléatoires de haute qualité, vous allez avoir un problème.

Considérez mon exemple. Les résultats possibles sont:

Rand()  freq. Rand() % 2
0       1/3   0
1       1/3   1
2       1/3   0

Par conséquent, les "queues" se produiront deux fois plus souvent que les "têtes"!

M. Atwood discute de cette question dans cet article de Coding Horror

6
Bob Kaufman

Comme d'autres l'ont noté, le simple fait d'utiliser un module va fausser les probabilités pour des nombres individuels, de sorte que des nombres plus petits sont préférables.

Une solution très ingénieuse et efficace à ce problème est utilisée dans la classe Java.util.Random de Java:

public int nextInt(int n) {
    if (n <= 0)
        throw new IllegalArgumentException("n must be positive");

    if ((n & -n) == n)  // i.e., n is a power of 2
        return (int)((n * (long)next(31)) >> 31);

    int bits, val;
    do {
        bits = next(31);
        val = bits % n;
    } while (bits - val + (n-1) < 0);
    return val;
}

Il m'a fallu un certain temps pour comprendre pourquoi cela fonctionne et je laisse cela comme exercice pour le lecteur, mais c'est une solution assez concise qui garantira que les nombres ont des probabilités égales.

La partie importante de ce morceau de code est la condition de la boucle while, qui rejette les nombres compris dans la plage de nombres qui, autrement, donnerait une distribution inégale.

5
Joey
double scale = 1.0 / ((double) Rand_MAX + 1.0);
int min, max;
...
rval = (int)(Rand() * scale * (max - min + 1) + min);
3
John Bode

Si vous ne vous souciez pas excessivement du «caractère aléatoire» des bits de poids faible, utilisez simplement Rand ()% HI_VAL.

Également:

(double)Rand() / (double)Rand_MAX;  // lazy way to get [0.0, 1.0)
2
genpfault

La façon naïve de le faire est:

int myRand = Rand() % 66; // for 0-65

Ce sera probablement une distribution très légèrement non uniforme (en fonction de votre valeur maximale), mais c'est assez proche.

Pour expliquer pourquoi ce n'est pas tout à fait uniforme, considérons cet exemple très simplifié:
Supposons que Rand_MAX vaut 4 et que vous voulez un nombre compris entre 0 et 2. Les valeurs possibles que vous pouvez obtenir sont indiquées dans ce tableau:

Rand()   |  Rand() % 3
---------+------------
0        |  0
1        |  1
2        |  2
3        |  0

Voir le problème? Si votre valeur maximale n'est pas un diviseur pair de Rand_MAX, vous aurez plus de chances de choisir de petites valeurs. Cependant, étant donné que Rand_MAX est généralement égal à 32767, le biais sera probablement assez petit pour qu’on puisse s’en tirer à bon compte.

Il existe différentes manières de contourner ce problème. voir ici pour une explication de la façon dont la Random de Java le gère.

2
Michael Myers

Mis à jour pour ne pas utiliser un #define

double Rand(double min, double max)
{
    return (double)Rand()/(double)Rand_MAX * (max - min) + min;
}
2
Mark Synowiec

Rand () renverra des nombres compris entre 0 et Rand_MAX, qui est au moins 32767.

Si vous voulez obtenir un nombre dans une plage, vous pouvez simplement utiliser modulo.

int value = Rand() % 66; // 0-65

Pour plus de précision, consultez cet article . Il explique pourquoi le modulo n’est pas forcément bon (mauvaises distributions, en particulier sur le haut de gamme) et propose diverses options.

1
Reed Copsey

En utilisant simplement Rand (), vous obtiendrez les mêmes nombres aléatoires lorsque vous exécuterez le programme plusieurs fois. c'est-à-dire lorsque vous exécuterez votre programme pour la première fois, il produira un nombre aléatoire x, y et z. Si vous exécutez à nouveau le programme, il produira les mêmes nombres x, y et z que ceux observés par moi.

La solution que j'ai trouvée pour le rendre unique à chaque fois utilise srand ()

Voici le code supplémentaire,

#include<stdlib.h>
#include<time.h>

time_t t;
srand((unsigned) time(&t));
int Rand_number = Rand() % (65 + 1 - 0) + 0 //i.e Random numbers in range 0-65.

Pour définir la plage, vous pouvez utiliser la formule suivante: Rand ()% (max_number + 1 - minimum_number) + minimum_number

J'espère que ça aide!

0
Jay Mehta
2 cents (ok 4 cents):

n = Rand()
x = result
l = limit

n/Rand_MAX = x/l

Refactor:

(l/1)*(n/Rand_MAX) = (x/l)*(l/1)

Gives:

x = l*n/Rand_MAX

int randn(int limit)

{

    return limit*Rand()/Rand_MAX;

}

int i;

for (i = 0; i < 100; i++) { 

    printf("%d ", randn(10)); 
    if (!(i % 16)) printf("\n"); 

}

> test
0
5 1 8 5 4 3 8 8 7 1 8 7 5 3 0 0
3 1 1 9 4 1 0 0 3 5 5 6 6 1 6 4
3 0 6 7 8 5 3 8 7 9 9 5 1 4 2 8
2 7 8 9 9 6 3 2 2 8 0 3 0 6 0 0
9 2 2 5 6 8 7 4 2 7 4 4 9 7 1 5
3 7 6 5 3 1 2 4 8 5 9 7 3 1 6 4
0 6 5
0
Scott Franco

Cette réponse ne se concentre pas sur le caractère aléatoire mais sur l'ordre arithmétique . Pour obtenir un nombre dans une plage, vous pouvez généralement le faire comme suit:

// the range is between [aMin, aMax]
double f = (double)Rand() / Rand_MAX;
double result = aMin + f * (aMax - aMin);

Cependant, il est possible que (aMax - aMin) déborde. Par exemple. aMax = 1, aMin = -DBL_MAX. Un moyen plus sûr est d'écrire comme ceci:

// the range is between [aMin, aMax]
double f = (double)Rand() / Rand_MAX;
double result = aMin - f * aMin + f * aMax;

Basé sur ce concept, quelque chose comme ceci peut causer un problème.

Rand() % (max_number + 1 - minimum_number) + minimum_number
// 1. max_number + 1 might overflow
// 2. max_number + 1 - min_number might overflow
0
QQVEI

Je pense que ce qui suit est-ce semi droite Cela fait longtemps que je n'ai pas touché C. L'idée est d'utiliser la division car le module ne donne pas toujours des résultats aléatoires. J'ai ajouté 1 à Rand_MAX car il y a autant de valeurs possibles provenant de Rand, y compris 0. Et puisque la plage est également 0 inclus, j'ai ajouté 1 également. Je pense que les maths sont arrangés correctement pour éviter les problèmes de nombres entiers.

#define MK_DIVISOR(max) ((int)((unsigned int)Rand_MAX+1/(max+1)))

num = Rand()/MK_DIVISOR(65);
0

Juste pour ajouter des détails supplémentaires aux réponses existantes.

L'opération mod % effectuera toujours une division complète et donnera donc un reste inférieur au diviseur.

x% y = x - (y * plancher ((x/y)))

Exemple de fonction de recherche de plage aléatoire avec commentaires:

uint32_t Rand_range(uint32_t n, uint32_t m) {
    // size of range, inclusive
    const uint32_t length_of_range = m - n + 1;

    // add n so that we don't return a number below our range
    return (uint32_t)(Rand() % length_of_range + n);
}

Une autre propriété intéressante comme ci-dessus:

x% y = x, si x <y

const uint32_t value = Rand_range(1, Rand_MAX); // results in Rand() % Rand_MAX + 1
// TRUE for all x = Rand_MAX, where x is the result of Rand()
assert(value == Rand_MAX);
result of Rand()
0
wulfgarpro

si vous vous souciez de la qualité de vos nombres aléatoires, n'utilisez pas Rand ()

utiliser un autre prng comme http://en.wikipedia.org/wiki/Mersenne_twister ou un autre prng de haute qualité

alors juste aller avec le module.

0
Spudd86