3783 votes

Comment générer des nombres entiers aléatoires dans une plage spécifique en Java ?

Comment puis-je générer un échantillon aléatoire int dans une fourchette spécifique ?

J'ai essayé les éléments suivants, mais ils ne fonctionnent pas :

Tentative 1 :

randomNum = minimum + (int)(Math.random() * maximum);

Bug : randomNum peut être plus grande que maximum .

Tentative 2 :

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum =  minimum + i;

Bug : randomNum peut être plus petite que minimum .

0 votes

Lorsque vous avez besoin d'un grand nombre de nombres aléatoires, je ne recommande pas la classe Random de l'API. Elle a juste une période trop petite. Essayez la classe Torsion de Mersenne au lieu de cela. Il y a une implémentation Java .

20 votes

Avant de poster une nouvelle réponse, pensez qu'il y a déjà plus de 65 réponses à cette question. Veillez à ce que votre réponse apporte des informations qui ne figurent pas parmi les réponses existantes.

0 votes

randomNum = minimum + (int)(Math.random() * (maximum - minimum);

4063voto

Greg Case Points 10300

Sur Java 1.7 ou supérieur La manière standard de procéder est la suivante :

import java.util.concurrent.ThreadLocalRandom;

// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);

Voir la JavaDoc pertinente . Cette approche a l'avantage de ne pas devoir initialiser explicitement un java.util.Random qui peut être une source de confusion et d'erreur si elle est utilisée de manière inappropriée.

Cependant, à l'inverse, il n'y a aucun moyen de définir explicitement la graine, il peut donc être difficile de reproduire les résultats dans des situations où cela est utile, par exemple pour tester ou sauvegarder des états de jeu ou autres. Dans ces situations, la technique pré-Java 1.7 présentée ci-dessous peut être utilisée.

Avant Java 1.7 La manière standard de procéder est la suivante :

import java.util.Random;

/**
 * Returns a pseudo-random number between min and max, inclusive.
 * The difference between min and max can be at most
 * <code>Integer.MAX_VALUE - 1</code>.
 *
 * @param min Minimum value
 * @param max Maximum value.  Must be greater than min.
 * @return Integer between min and max, inclusive.
 * @see java.util.Random#nextInt(int)
 */
public static int randInt(int min, int max) {

    // NOTE: This will (intentionally) not run as written so that folks
    // copy-pasting have to think about how to initialize their
    // Random instance.  Initialization of the Random instance is outside
    // the main scope of the question, but some decent options are to have
    // a field that is initialized once and then re-used as needed or to
    // use ThreadLocalRandom (if using at least Java 1.7).
    // 
    // In particular, do NOT do 'Random rand = new Random()' here or you
    // will get not very good / not very random results.
    Random rand;

    // nextInt is normally exclusive of the top value,
    // so add 1 to make it inclusive
    int randomNum = rand.nextInt((max - min) + 1) + min;

    return randomNum;
}

Voir la JavaDoc pertinente . Dans la pratique, le java.util.Random est souvent préférable à la classe [java.lang.Math.random()](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Math.html#random()) .

En particulier, il n'est pas nécessaire de réinventer la roue de la génération d'entiers aléatoires lorsqu'il existe une API simple dans la bibliothèque standard pour accomplir cette tâche.

47 votes

Pour les appels où max valeur est Integer.MAX_VALUE il est possible de déborder, ce qui entraîne une défaillance du système. java.lang.IllegalArgumentException . Vous pouvez essayer avec : randInt(0, Integer.MAX_VALUE) . De même, si nextInt((max-min) + 1) renvoie la valeur la plus élevée (assez rare, je suppose) ne va-t-il pas déborder à nouveau (en supposant que min et max sont des valeurs suffisamment élevées) ? Comment faire face à ce genre de situation ?

1 votes

@momo le RANDOM La classe supporte nextLong . Vous pouvez l'utiliser à la place de nextInt pour les longs.

3 votes

@MoisheLipsker Cela doit être que nextLong ne prend pas une limite comme nextInteger.

1475voto

TJ_Fischer Points 9042

Notez que cette approche est plus biaisée et moins efficace qu'une nextInt approche, https://stackoverflow.com/a/738651/360211

Un modèle standard pour y parvenir est le suivant :

Min + (int)(Math.random() * ((Max - Min) + 1))

Le site Java La fonction de la bibliothèque mathématique Math.random() génère une valeur double dans l'intervalle suivant [0,1) . Notez que cette gamme n'inclut pas le 1.

Pour obtenir d'abord une gamme spécifique de valeurs, vous devez multiplier par la magnitude de la gamme de valeurs que vous voulez couvrir.

Math.random() * ( Max - Min )

Cela renvoie une valeur dans l'intervalle [0,Max-Min) où "Max-Min" n'est pas inclus.

Par exemple, si vous voulez [5,10) vous avez besoin de couvrir cinq valeurs entières, vous utilisez donc

Math.random() * 5

Cela renverrait une valeur dans l'intervalle [0,5) où 5 n'est pas inclus.

Vous devez maintenant déplacer cette plage vers le haut, jusqu'à la plage que vous ciblez. Pour ce faire, vous ajoutez la valeur Min.

Min + (Math.random() * (Max - Min))

Vous obtiendrez maintenant une valeur dans l'intervalle [Min,Max) . En suivant notre exemple, cela signifie [5,10) :

5 + (Math.random() * (10 - 5))

Mais, cela n'inclut toujours pas Max et vous obtenez une double valeur. Afin d'obtenir le Max inclus, vous devez ajouter 1 à votre paramètre d'intervalle. (Max - Min) et ensuite tronquer la partie décimale en la transformant en un int. Ceci est accompli via :

Min + (int)(Math.random() * ((Max - Min) + 1))

Et voilà, vous l'avez. Une valeur entière aléatoire dans l'intervalle [Min,Max] ou selon l'exemple [5,10] :

5 + (int)(Math.random() * ((10 - 5) + 1))

86 votes

La documentation Sun indique explicitement qu'il vaut mieux utiliser Random() si vous avez besoin d'un int plutôt que Math.random() qui produit un double.

6 votes

Cette méthode est en fait biaisée par rapport à la méthode nextInt. stackoverflow.com/a/738651/360211

6 votes

"Biaisé" dans ce cas signifie qu'après 2^53 exécutions, certains nombres auront eu une occurrence supplémentaire, en moyenne.

412voto

Utilisez :

Random ran = new Random();
int x = ran.nextInt(6) + 5;

Le nombre entier x est maintenant le nombre aléatoire qui a un résultat possible de 5-10 .

182voto

krosenvold Points 35979

Utilisez :

minimum + rn.nextInt(maxValue - minvalue + 1)

171voto

ZouZou Points 23600

Avec java-8 ils ont introduit la méthode ints(int randomNumberOrigin, int randomNumberBound) dans le Random classe.

Par exemple, si vous voulez générer cinq nombres entiers aléatoires (ou un seul) dans l'intervalle [0, 10], il suffit de le faire :

Random r = new Random();
int[] fiveRandomNumbers = r.ints(5, 0, 11).toArray();
int randomNumber = r.ints(1, 0, 11).findFirst().getAsInt();

Le premier paramètre indique uniquement la taille de l IntStream généré (qui est la méthode surchargée de celle qui produit un nombre illimité de IntStream ).

Si vous devez effectuer plusieurs appels séparés, vous pouvez créer un itérateur primitif infini à partir du flux :

public final class IntRandomNumberGenerator {

    private PrimitiveIterator.OfInt randomIterator;

    /**
     * Initialize a new random number generator that generates
     * random numbers in the range [min, max]
     * @param min - the min value (inclusive)
     * @param max - the max value (inclusive)
     */
    public IntRandomNumberGenerator(int min, int max) {
        randomIterator = new Random().ints(min, max + 1).iterator();
    }

    /**
     * Returns a random number in the range (min, max)
     * @return a random number in the range (min, max)
     */
    public int nextInt() {
        return randomIterator.nextInt();
    }
}

Vous pouvez également le faire pour double et long valeurs. J'espère que cela vous aidera ! :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X