web-dev-qa-db-fra.com

Générer un nombre aléatoire dans la plage?

Duplicata possible:
Génération de nombres aléatoires dans Objective-C

Comment générer un nombre aléatoire qui se situe dans une plage?

16
TheLearner

C'est en fait un peu plus difficile à obtenir vraiment correct que la plupart des gens ne le pensent:

int Rand_lim(int limit) {
/* return a random number between 0 and limit inclusive.
 */

    int divisor = Rand_MAX/(limit+1);
    int retval;

    do { 
        retval = Rand() / divisor;
    } while (retval > limit);

    return retval;
}

Tentatives qui utilisent simplement % (ou équivalent, /) pour obtenir les nombres dans une plage introduisant presque inévitablement un biais (c'est-à-dire que certains nombres seront générés plus souvent que d'autres).

Quant à savoir pourquoi utiliser % produit des résultats asymétriques: à moins que la plage souhaitée ne soit un diviseur de Rand_MAX, l'inclinaison est inévitable. Si vous commencez avec de petits nombres, il est assez facile de comprendre pourquoi. Pensez à prendre 10 bonbons (que nous supposerons que vous ne pouvez pas couper, casser, etc. en plus petits morceaux) et essayez de le répartir également entre trois enfants. De toute évidence, cela ne peut pas être fait - si vous distribuez tous les bonbons, le plus proche que vous pouvez obtenir est que deux enfants obtiennent trois morceaux de bonbons et l'un d'eux quatre.

Il n'y a qu'une seule façon pour tous les enfants d'obtenir le même nombre de bonbons: assurez-vous de ne pas distribuer du tout le dernier bonbon.

Pour relier cela au code ci-dessus, commençons par numéroter les bonbons de 1 à 10 et les enfants de 1 à 3. La division initiale dit qu'il y a trois enfants, notre diviseur est trois. Nous tirons ensuite un bonbon aléatoire du seau, regardons son nombre et divisons par trois et le remettons à cet enfant - mais si le résultat est supérieur à 3 (c'est-à-dire que nous avons choisi le bonbon numéro 10), nous ne le faisons tout simplement pas distribuez-le du tout - nous le jetons et choisissons un autre bonbon.

Bien sûr, si vous utilisez une implémentation moderne de C++ (c'est-à-dire qui prend en charge C++ 11 ou plus récent), vous devez généralement utiliser l'une des classes distribution de la bibliothèque standard. Le code ci-dessus correspond le mieux à std::uniform_int_distribution, mais la bibliothèque standard comprend également uniform_real_distribution ainsi que des classes pour un certain nombre de distributions non uniformes (Bernoulli, Poisson, normal, peut-être quelques autres dont je ne me souviens pas pour le moment).

70
Jerry Coffin
int Rand_range(int min_n, int max_n)
{
    return Rand() % (max_n - min_n + 1) + min_n;
}

Pour les fractions:

double Rand_range(double min_n, double max_n)
{
    return (double)Rand()/Rand_MAX * (max_n - min_n) + min_n;
}
7
Michał Trybus

Pour une valeur entière dans la plage [min, max):

double scale = (double) (max - min) / Rand_MAX;
int val = min + floor(Rand() * scale) 
1
John Bode