Come posso generare numeri interi casuali entro un intervallo specifico in Java?

Come posso generare un valore int casuale in un intervallo specifico?

Ho provato i seguenti, ma non funzionano:

Tentativo 1:

randomNum = minimum + (int)(Math.random() * maximum);
// Bug: `randomNum` can be bigger than `maximum`.

Tentativo 2:

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum =  minimum + i;
// Bug: `randomNum` can be smaller than `minimum`.

In Java 1.7 o successivo, il modo standard per farlo è il seguente:

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);

Vedere il relativo JavaDoc. Questo approccio ha il vantaggio di non dover inizializzare esplicitamente un'istanza di java.util.Random, che può essere fonte di confusione ed errore se usato in modo inappropriato.

Tuttavia, al contrario, non c'è modo di impostare esplicitamente il seme, quindi può essere difficile riprodurre i risultati in situazioni in cui ciò è utile, come i test o il salvataggio degli stati di gioco o simili. In queste situazioni, si può usare la tecnica pre-Java 1.7 mostrata qui sotto.

Prima di Java 1.7, il modo standard per farlo è il seguente:

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;
}

Vedere il relativo JavaDoc. In pratica, la classe java.util.Random è spesso preferibile a java.lang.Math.random().

In particolare, non c'è bisogno di reinventare la ruota della generazione di numeri interi casuali quando c'è un'API diretta all'interno della libreria standard per eseguire il compito.

Commentari (18)

Utilizzare:

minimum + rn.nextInt(maxValue - minvalue + 1)
Commentari (0)
 rand.nextInt((max+1) - min) + min;
Commentari (0)