util - rand java 8




Come generare numeri casuali all'interno di un intervallo specifico in Java? (20)

Come posso generare un valore int casuale 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`.

https://code.i-harness.com


A partire da Java 7, non dovresti più usare Random . Per la maggior parte degli usi, il generatore di numeri casuali di scelta è ora ThreadLocalRandom .

Per i pool di fork join e i flussi paralleli, utilizzare SplittableRandom .

Joshua Bloch. Efficace Java. Terza edizione.

A partire da Java 8

Per i pool di fork join e i flussi paralleli, utilizzare SplittableRandom che è in genere più veloce, ha una migliore indipendenza statistica e proprietà di uniformità rispetto a Random .

Per generare un intervallo casuale nell'intervallo [0, 1_000]:

int n = new SplittableRandom().nextInt(0, 1_001);

Per generare una matrice di valori int[100] casuali nell'intervallo [0, 1_000]:

int[] a = new SplittableRandom().ints(100, 0, 1_001).parallel().toArray();

Per restituire un flusso di valori casuali:

IntStream stream = new SplittableRandom().ints(100, 0, 1_001);

È meglio usare SecureRandom piuttosto che solo Random.

public static int generateRandomInteger(int min, int max) {
    SecureRandom rand = new SecureRandom();
    rand.setSeed(new Date().getTime());
    int randomNum = rand.nextInt((max - min) + 1) + min;
    return randomNum;
}

Con java-8 hanno introdotto gli ints(int randomNumberOrigin, int randomNumberBound) del metodo ints(int randomNumberOrigin, int randomNumberBound) nella classe Random .

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 IntStream generato (che è il metodo sovraccarico di quello che produce un IntStream illimitato).

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 valori double e long .

Spero che sia d'aiuto! :)


Ecco un semplice esempio che mostra come generare un numero casuale da un intervallo chiuso [min, max] , mentre min <= max is true

Puoi riutilizzarlo come campo in classe buca, avendo anche tutti i metodi Random.class in un posto

Esempio di risultati:

RandomUtils random = new RandomUtils();
random.nextInt(0, 0); // returns 0
random.nextInt(10, 10); // returns 10
random.nextInt(-10, 10); // returns numbers from -10 to 10 (-10, -9....9, 10)
random.nextInt(10, -10); // throws assert

fonti:

import junit.framework.Assert;
import java.util.Random;

public class RandomUtils extends Random {

    /**
     * @param min generated value. Can't be > then max
     * @param max generated value
     * @return values in closed range [min, max].
     */
    public int nextInt(int min, int max) {
        Assert.assertFalse("min can't be > then max; values:[" + min + ", " + max + "]", min > max);
        if (min == max) {
            return max;
        }

        return nextInt(max - min + 1) + min;
    }
}

Facciamo un esempio.

Supponiamo di voler generare un numero compreso tra 5 e 10 :

int max = 10;
int min = 5;
int diff = max - min;
Random rn = new Random();
int i = rn.nextInt(diff + 1);
i += min;
System.out.print("The Random Number is " + i);

Cerchiamo di capirlo ...

Inizializza max con il valore più alto e min con il valore più basso.

Ora, dobbiamo determinare quanti valori possibili possono essere ottenuti. Per questo esempio, sarebbe:

5, 6, 7, 8, 9, 10

Quindi, il conteggio di questo sarebbe max - min + 1.

cioè 10 - 5 + 1 = 6

Il numero casuale genererà un numero compreso tra 0 e 5 .

cioè 0, 1, 2, 3, 4, 5

L'aggiunta del valore minimo al numero casuale produrrebbe:

5, 6, 7, 8, 9, 10

Quindi otteniamo la gamma desiderata.


Generare un numero casuale per la differenza di min e max usando il nextint(n) e quindi aggiungere il numero min al risultato:

Random rn = new Random();
int result = rn.nextInt(max - min + 1) + min;
System.out.println(result);

In Java 1.7 o versioni successive , 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);

Vedi il relativo JavaDoc . Questo approccio ha il vantaggio di non dover inizializzare esplicitamente un'istanza java.util.Random , 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;
}

Vedi il relativo JavaDoc . In pratica, la classe java.util.Random è 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.


In caso di lancio di un dado, sarebbe un numero casuale compreso tra 1 e 6 (non da 0 a 6), quindi:

face = 1 + randomNumbers.nextInt(6);


Perdonami per essere meticoloso, ma la soluzione suggerita dalla maggioranza, cioè min + rng.nextInt(max - min + 1)) , sembra pericolosa a causa del fatto che:

  • rng.nextInt(n) non può raggiungere Integer.MAX_VALUE .
  • (max - min) può causare overflow quando min è negativo.

Una soluzione infallibile restituirebbe risultati corretti per qualsiasi min <= max entro [ Integer.MIN_VALUE , Integer.MAX_VALUE ]. Considera la seguente implementazione ingenua:

int nextIntInRange(int min, int max, Random rng) {
   if (min > max) {
      throw new IllegalArgumentException("Cannot draw random int from invalid range [" + min + ", " + max + "].");
   }
   int diff = max - min;
   if (diff >= 0 && diff != Integer.MAX_VALUE) {
      return (min + rng.nextInt(diff + 1));
   }
   int i;
   do {
      i = rng.nextInt();
   } while (i < min || i > max);
   return i;
}

Sebbene inefficiente, si noti che la probabilità di successo nel ciclo while sarà sempre del 50% o superiore.



Questo metodo potrebbe essere comodo da usare:

Questo metodo restituirà un numero casuale tra il valore min e max fornito:

public static int getRandomNumberBetween(int min, int max) {
    Random foo = new Random();
    int randomNumber = foo.nextInt(max - min) + min;
    if (randomNumber == min) {
        // Since the random number is between the min and max values, simply add 1
        return min + 1;
    } else {
        return randomNumber;
    }
}

e questo metodo restituirà un numero casuale dal valore min e max fornito (quindi il numero generato potrebbe anche essere il numero minimo o massimo):

public static int getRandomNumberFrom(int min, int max) {
    Random foo = new Random();
    int randomNumber = foo.nextInt((max + 1) - min) + min;

    return randomNumber;
}

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

Uno schema standard per realizzare questo è:

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

La funzione di libreria Math Math 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 )

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

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

Math.random() * 5

Ciò restituirebbe un valore nell'intervallo [0,5) , in cui 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, ciò significa [5,10) :

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

Ma questo non include ancora Max e ottieni un doppio valore. Per ottenere il valore Max incluso, devi aggiungere 1 al tuo parametro di 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))

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


Un'altra opzione è solo usando Apache Commons :

import org.apache.commons.math.random.RandomData;
import org.apache.commons.math.random.RandomDataImpl;

public void method() {
    RandomData randomData = new RandomDataImpl();
    int number = randomData.nextInt(5, 10);
    // ...
 }

Usa la classe Random :

Random ran = new Random();
// Assumes max and min are non-negative.
int randomInt = min + ran.nextInt(max - min + 1);

Uso:

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

 rand.nextInt((max+1) - min) + min;

private static Random random = new Random();    

public static int getRandomInt(int min, int max){
  return random.nextInt(max - min + 1) + min;
}

O

public static int getRandomInt(Random random, int min, int max)
{
  return random.nextInt(max - min + 1) + min;
}

public static Random RANDOM = new Random(System.nanoTime());

public static final float random(final float pMin, final float pMax) {
    return pMin + RANDOM.nextFloat() * (pMax - pMin);
}






integer