Domanda Come posso generare numeri casuali all'interno di un intervallo specifico in Java?


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

Ho provato quanto segue, ma quelli 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`.

2896
2017-12-12 18:20


origine


risposte:


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 a java.util.Random istanza, che può essere fonte di confusione ed errore se usata in modo inappropriato.

Tuttavia, viceversa, non è possibile impostare in modo esplicito il seed in modo che possa essere difficile riprodurre i risultati in situazioni in cui ciò è utile, come test o salvataggio di stati di gioco o simili. In queste situazioni, è possibile utilizzare la tecnica pre-Java 1.7 mostrata di seguito.

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, il java.util.Random la classe è spesso preferibile a java.lang.Math.random ().

In particolare, non è necessario reinventare la ruota di generazione di numeri casuali quando vi è un'API semplice all'interno della libreria standard per eseguire l'operazione.


3251
2017-12-12 18:25



Si noti che questo approccio è più parziale e meno efficiente di a nextInt approccio, https://stackoverflow.com/a/738651/360211

Uno schema standard per realizzare questo è:

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

Il Giava Funzione di libreria matematica Math.random () genera un doppio valore nell'intervallo [0,1). Si noti che questo intervallo non include il 1.

Per ottenere innanzitutto un intervallo di valori specifico, è necessario moltiplicare per la grandezza dell'intervallo di valori che si desidera coprire.

Math.random() * ( Max - Min )

Questo restituisce un valore nell'intervallo [0,Max-Min), dove 'Max-Min' non è incluso.

Ad esempio, se vuoi [5,10), è necessario coprire cinque valori interi in modo da utilizzare

Math.random() * 5

Ciò restituirebbe un valore nell'intervallo [0,5), dove 5 non è incluso.

Ora devi spostare questo intervallo fino all'intervallo che hai scelto come target. Lo fai aggiungendo il valore Min.

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

Ora otterrai un valore nell'intervallo [Min,Max). Seguendo il nostro esempio, significa [5,10):

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

Ma questo non include ancora Max e ottieni un doppio valore. Al fine di ottenere il Max valore incluso, è necessario aggiungere 1 al parametro intervallo (Max - Min) e quindi troncare la parte decimale eseguendo il casting su un int. Questo è realizzato tramite:

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

E il gioco è fatto. Un valore intero casuale nell'intervallo [Min,Max]o per l'esempio [5,10]:

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

1323
2017-12-12 18:35



Uso:

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

L'intero x è ora il numero casuale che ha un possibile risultato di 5-10.


311
2017-09-04 04:23



Uso:

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

122
2017-12-12 18:25



Con  hanno introdotto il metodo ints(int randomNumberOrigin, int randomNumberBound) nel Random classe.

Ad esempio, se vuoi generare cinque numeri interi casuali (o uno solo) nell'intervallo [0, 10], esegui semplicemente:

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

Il primo parametro indica solo la dimensione del IntStream generato (che è il metodo sovraccarico di quello che produce un numero illimitato IntStream).

Se devi effettuare più chiamate separate, puoi creare un iteratore primitivo infinito dallo stream:

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

Puoi anche farlo per double e long valori.

Spero che sia d'aiuto! :)


98
2017-11-26 18:29



Puoi modificare il tuo secondo esempio di codice per:

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

90
2017-12-12 18:31



Solo una piccola modifica della tua prima soluzione sarebbe sufficiente.

Random rand = new Random();
randomNum = minimum + rand.nextInt((maximum - minimum) + 1);

Vedi di più qui per l'implementazione di Random


89
2018-03-12 22:44



ThreadLocalRandom equivalente della classe java.util.Random per l'ambiente multithread. La generazione di un numero casuale viene eseguita localmente in ciascuna delle discussioni. Quindi abbiamo una performance migliore riducendo i conflitti.

int rand = ThreadLocalRandom.current().nextInt(x,y);

x, y - intervalli per es. (1,10)


54
2018-02-12 23:19