1. Números pseudoaleatorios

A veces, un programador se enfrenta a tareas aparentemente sencillas: "seleccionar una película aleatoria de una lista determinada", "elegir un ganador de la lotería", "reproducir aleatoriamente la lista de reproducción cuando el usuario agita su teléfono inteligente", "elegir un número aleatorio para cifrar un mensaje". , etc. En cada caso, el desarrollador hace una pregunta lógica: ¿cómo obtener un número aleatorio?

En realidad, obtener un número verdaderamente aleatorio es bastante difícil de hacer. De hecho, es tan difícil que se incorporan coprocesadores matemáticos especiales en algunas computadoras para generar números que satisfagan todos los requisitos para una verdadera aleatoriedad.

A los programadores se les ocurrió su propia solución: números pseudoaleatorios . Los números pseudoaleatorios son un tipo de secuencia, cuyos números parecen ser aleatorios. Sin embargo, al realizar un análisis cuidadoso, un experto puede encontrar ciertos patrones en la secuencia. Dichos números no son adecuados para cifrar documentos secretos, pero son suficientes para simular el lanzamiento de un dado en un juego.

Hay muchos algoritmos para generar una secuencia de números pseudoaleatorios. Casi todos generan el siguiente número aleatorio en función del número anterior y algunos números auxiliares adicionales.

Por ejemplo, este programa mostrará 1000números que no se repiten:

public class Main
{
   public static int a = 41;
   public static int c = 11119;
   public static int m = 11113;
   public static int seed = 1;

   public static int getNextRandom()
   {
     seed = (a * seed + c) % m;
     return seed;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 1000; i++)
     {
       System.out.println(getNextRandom());
     }
   }
}

Por cierto, aquí no estamos hablando de números pseudoaleatorios. Estamos hablando de una secuencia de números pseudoaleatorios. Mirando un solo número, es imposible saber si es aleatorio o no.

De hecho, hay varias formas de obtener un número aleatorio:

public static int getRandomNumber()
{
   return 4; // Here's a random number (we got it by rolling a die)
}

2.Math.random()

En Java, la Mathclase tiene un método especial que devuelve un número aleatorio. Y como puede suponer, el método se llama random. En general, esto es lo que parece llamar a este método:

Math.random()

Este método no toma parámetros y devuelve un número real pseudoaleatorio en el rango de 0a 1. El número 1 en sí no está incluido en el rango.

Ejemplo:

Código Salida de consola
public class Main
{
   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       System.out.println(Math.random());
     }
   }
} 
0.9703753971734451
0.09979423801773157
0.994048474709053
0.2852203204171295
0.13551248551226025
0.3128547131272822
0.5342480554101412
0.6817369932044817
0.1840767788961758
0.06969563435451254

Pero, ¿y si este método no es exactamente lo que necesita? Suponga que desea escribir un programa que simule lanzar un dado de seis caras. ¿Cómo obtienes números enteros aleatorios en el rango 1..6, en lugar de números reales en el rango 0..1?

En realidad es bastante simple.

Primero, debe mapear el rango [0, 1)en [0, 6). Para hacer esto, simplemente multiplique el resultado devuelto random()por 6. Por supuesto, para obtener números enteros, debe redondear:

Código Salida de consola
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6);
   }

   public static void main(String[] args)
   {
      for (int i = 0; i < 10; i++)
      {
         int x = getRandomDieNumber();
         System.out.println(x);
      }
   }
}
5
2
3
3
2
4
1
1
5
0

devuelve getRandomDieNumber()un entero aleatorio en el rango 0..5inclusive. Pero no será un número en el conjunto 1, 2, 3, 4, 5, 6. Será un número en el conjunto 0, 1, 2, 3, 4, 5.

Si lo que necesita son números en el conjunto 1, 2, 3, 4, 5, 6, simplemente agregue uno a los números aleatorios:

Código Salida de consola
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6) + 1;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       int x = getRandomDieNumber();
       System.out.println(x);
     }
   }
}
3
2
1
3
6
5
6
1
6
6

¡Eso es perfecto!



3. Randomclase

Java tiene una Randomclase especial que encapsula una secuencia de números pseudoaleatorios. Puede crear varios objetos de la Randomclase. Cada uno de estos objetos generará su propia secuencia de números pseudoaleatorios.

Esta es una clase súper interesante con muchos métodos interesantes. Empecemos por lo más sencillo.

double nextDouble()

Este método devuelve un número real aleatorio en el rango 0.0- 1.0. Es muy similar al Math.random()método. Y no es de extrañar, ya que el Math.random()método simplemente llama al nextDouble()método en un Randomobjeto.

float nextFloat()

Este método es muy similar al nextDouble()método, pero el número aleatorio devuelto es un float. También se encuentra en el rango 0.0- 1.0. Y, como siempre en Java, el rango no incluye el número 1.0en sí.

Random r = new Random();
float f = r.nextFloat();

int nextInt(int max)

Este método devuelve un número entero aleatorio en el rango [0, max). 0está incluido en la gama, pero maxno lo está.

En otras palabras, si desea obtener un número aleatorio en el conjunto 1, 2, 3, 4, 5, 6, debe agregar uno al número aleatorio devuelto:

Random r = new Random();
int x = r.nextInt(6) + 1;

int nextInt()

Este método es similar al anterior, pero no toma ningún parámetro. Entonces, ¿cuál es el rango de sus valores de retorno? De -2 billiona +2 billion.

Bueno, para ser precisos, de -2147483648a +2147483647.

long nextLong()

Este método es similar al nextInt()método, pero el valor devuelto caerá en algún lugar del rango posible completo de longs.

boolean nextBoolean()

Este método devuelve un booleanvalor aleatorio: falseo true. Esto es muy conveniente cuando necesita obtener una secuencia larga de valores booleanos aleatorios.

void nextBytes(byte[] data)

Este método no devuelve nada (ya que el tipo de retorno es void). En cambio, llena la matriz pasada con valores aleatorios. Esto es muy útil cuando necesita un gran búfer lleno de datos aleatorios.

double nextGaussian()

Este método devuelve un número real aleatorio en el rango 0.0- 1.0. Sin embargo, los números no están distribuidos uniformemente en este rango. En cambio, siguen una distribución normal .

Los valores cerca de la mitad del rango ( 0.5) ocurrirán con más frecuencia que los valores en los extremos del rango.

Clase aleatoria

En nuestro caso, el pico de la distribución de valor estará en0.5