Pregunta ¿Cómo puedo generar enteros aleatorios dentro de un rango específico en Java?


¿Cómo puedo generar un azar int valor en un rango específico?

He intentado lo siguiente, pero esos no funcionan:

Intento 1:

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

Intento 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`.

2897
2017-12-12 18:20


origen


Respuestas:


En Java 1.7 o posterior, la forma estándar de hacerlo es la siguiente:

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

Ver el JavaDoc relevante. Este enfoque tiene la ventaja de no necesitar inicializar explícitamente un java.util.Random ejemplo, que puede ser una fuente de confusión y error si se usa de manera inapropiada.

Sin embargo, a la inversa, no hay forma de establecer explícitamente la semilla, por lo que puede ser difícil reproducir los resultados en situaciones en las que es útil, como probar o guardar estados de juego o similares. En esas situaciones, se puede utilizar la técnica anterior a Java 1.7 que se muestra a continuación.

Antes de Java 1.7, la forma estándar de hacerlo es la siguiente:

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

Ver el JavaDoc relevante. En la práctica, el java.util.Random clase es a menudo preferible java.lang.Math.random ().

En particular, no hay necesidad de reinventar la rueda de generación de enteros aleatorios cuando hay una API directa dentro de la biblioteca estándar para realizar la tarea.


3254
2017-12-12 18:25



Tenga en cuenta que este enfoque es más parcial y menos eficiente que una nextInt enfoque, https://stackoverflow.com/a/738651/360211

Un patrón estándar para lograr esto es:

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

los Java Función de biblioteca matemática Math.random () genera un valor doble en el rango [0,1). Observe que este rango no incluye el 1.

Para obtener primero un rango específico de valores, debe multiplicar por la magnitud del rango de valores que desea cubrir.

Math.random() * ( Max - Min )

Esto devuelve un valor en el rango [0,Max-Min), donde 'Max-Min' no está incluido.

Por ejemplo, si quieres [5,10), necesitas cubrir cinco valores enteros para que uses

Math.random() * 5

Esto devolvería un valor en el rango [0,5), donde 5 no está incluido.

Ahora necesita cambiar este rango al rango al que apunta. Usted hace esto agregando el valor Min.

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

Ahora obtendrás un valor en el rango [Min,Max). Siguiendo nuestro ejemplo, eso significa [5,10):

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

Pero, esto aún no incluye Max y obtendrás un doble valor. Para obtener el Max valor incluido, necesita agregar 1 a su parámetro de rango (Max - Min) y luego truncar la parte decimal al convertir a un int. Esto se logra a través de:

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

Y ahí lo tienes. Un valor entero aleatorio en el rango [Min,Max]o por el ejemplo [5,10]:

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

1323
2017-12-12 18:35



Utilizar:

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

El número entero x ahora es el número aleatorio que tiene un posible resultado de 5-10.


311
2017-09-04 04:23



Utilizar:

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

122
2017-12-12 18:25



Con  ellos introdujeron el método ints(int randomNumberOrigin, int randomNumberBound) en el Random clase.

Por ejemplo, si desea generar cinco enteros aleatorios (o uno solo) en el rango [0, 10], simplemente haga lo siguiente:

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

El primer parámetro indica solo el tamaño del IntStream generado (que es el método sobrecargado del que produce un ilimitado IntStream)

Si necesita hacer múltiples llamadas por separado, puede crear un iterador primitivo infinito de la secuencia:

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

También puedes hacerlo por double y long valores.

¡Espero eso ayude! :)


98
2017-11-26 18:29



Puede editar su segundo ejemplo de código para:

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

90
2017-12-12 18:31



Solo una pequeña modificación de su primera solución sería suficiente.

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

Vea más aquí para la implementación de Random


89
2018-03-12 22:44



ThreadLocalRandom equivalente a la clase java.util.Random para entornos multiproceso. La generación de un número aleatorio se lleva a cabo localmente en cada uno de los hilos. Entonces, tenemos un mejor desempeño al reducir los conflictos.

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

x, y - intervalos, p. (1,10)


54
2018-02-12 23:19



los Math.Random clase en Java está basado en 0 Entonces, si escribes algo como esto:

Random rand = new Random();
int x = rand.nextInt(10);

x será entre 0-9 inclusivo.

Entonces, dada la siguiente matriz de 25 artículos, el código para generar un número aleatorio entre 0 (la base de la matriz) y array.length sería:

String[] i = new String[25];
Random rand = new Random();
int index = 0;

index = rand.nextInt( i.length );

Ya que i.length regresará 25, el nextInt( i.length ) devolverá un número entre el rango de 0-24. La otra opción va con Math.Random que funciona de la misma manera.

index = (int) Math.floor(Math.random() * i.length);

Para una mejor comprensión, echa un vistazo a la publicación del foro Random Intervals (archive.org).


53
2018-01-08 15:04



Perdóname por ser exigente, pero la solución sugerida por la mayoría, es decir, min + rng.nextInt(max - min + 1)), parece peligroso debido al hecho de que:

  • rng.nextInt(n) no puedo alcanzar Integer.MAX_VALUE.
  • (max - min) puede causar desbordamiento cuando min es negativo

Una solución infalible devolvería resultados correctos para cualquier min <= max dentro [Integer.MIN_VALUE, Integer.MAX_VALUE] Considere la siguiente implementación 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;
}

Aunque ineficiente, tenga en cuenta que la probabilidad de éxito en el while loop siempre será 50% o más.


43
2018-01-10 13:19



Me pregunto si alguno de los métodos de generación de números aleatorios proporcionados por un Apache Commons Math la biblioteca encajaría en la cuenta.

Por ejemplo: RandomDataGenerator.nextInt o RandomDataGenerator.nextLong


25
2017-12-12 18:27