Los números aleatorios

prev.gif (997 bytes)chapter.gif (1105 bytes)home.gif (1054 bytes)next.gif (998 bytes)

Clases y objetos

La clase Random

Comprobación de la uniformidad de los números aleatorios

Secuencias de números aleatorios


La clase Random

disco.gif (1035 bytes)azar: AzarApp.java

Del mismo modo que hemos visualizado el código fuente de la clase String, también la podemos obtener el de la clase Random. Situamos el cursor en el nombre de la clase y seleccionamos el primer elemento del menú flotante Browse symbol at cursor que aparece cuando se pulsa el botón derecho del ratón.

La clase Random proporciona un generador de números aleatorios que es más flexible que la función estática random de la clase Math.

Para crear una secuencia de números aleatorios tenemos que seguir los siguientes pasos:

  1. Proporcionar a nuestro programa información acerca de la clase Random. Al principio del programa  escribiremos la siguiente sentencia.
	import java.util.Random;
  1. Crear un objeto de la clase Random
  2. Llamar a una de las funciones miembro que generan un número aleatorio
  3. Usar el número aleatorio.

 

Constructores

La clase dispone de dos constructores, el primero crea un generador de números aleatorios cuya semilla es inicializada en base al instante de tiempo actual.

    	Random rnd = new Random();

El segundo, inicializa la semilla con un número del tipo long.

   	Random rnd = new Random(3816L);

El sufijo L no es necesario, ya que aunque 3816 es un número int por defecto, es promocionado automáticamente a long.

Aunque no podemos predecir que números se generarán con una semilla particular, podemos sin embargo, duplicar una serie de números aleatorios usando la misma semilla. Es decir, cada vez que creamos un objeto de la clase Random con la misma semilla obtendremos la misma secuencia de números aleatorios. Esto no es útil en el caso de loterias, pero puede ser útil en el caso de juegos,  exámenes basados en una secuencia de preguntas aleatorias, las mismas para cada uno de los estudiantes, simulaciones que se repitan de la misma forma una y otra vez, etc.

 

Funciones miembro

Podemos cambiar la semilla de los números aleatorios en cualquier momento, llamando a la función miembro setSeed.

    	rnd.setSeed(3816);

Podemos generar números aleatorios en cuatro formas diferentes:

	rnd.nextInt();

genera un número aleatorio entero de tipo int

	rnd.nextLong();

genera un número aleatorio entero de tipo long

	rnd.nextFloat();

genera un número aleatorio de tipo float entre 0.0 y 1.0, aunque siempre menor que 1.0

	rnd.nextDouble();

genera un número aleatorio de tipo double entre 0.0 y 1.0, aunque siempre menor que 1.0

Casi siempre usaremos esta última versión. Por ejemplo, para generar una secuencia de 10 números aleatorios entre 0.0 y 1.0 escribimos

    for (int i = 0; i < 10; i++) {
        System.out.println(rnd.nextDouble());;
    }

Para crear una secuencia de 10 números aleatorios enteros comprendidos entre 0 y 9 ambos incluídos escribimos

    	int x;
	for (int i = 0; i < 10; i++) {
        	x = (int)(rnd.nextDouble() * 10.0);
        	System.out.println(x);
    	}

(int) transforma un número decimal double en entero int eliminando la parte decimal.

 

Comprobación de la uniformidad de los números aleatorios

Podemos comprobar la uniformidad de los números aleatorios generando una secuencia muy grande de números aleatorios enteros comprendios entre 0 y 9 ambos inclusive. Contamos cuantos ceros aparecen en la secuencia, cuantos unos, ... cuantos nueves, y guardamos estos datos en los elementos de un array.

Primero creamos un array ndigitos de 10 de elementos que son enteros.

    int[] ndigitos = new int[10];

Inicializamos los elementos del array a cero.

    for (int i = 0; i < 10; i++) {
        ndigitos[i] = 0;
    }

Creamos una secuencia de 100000 números aleatorios enteros comprendidos entre 0 y 9 ambos inclusive (véase el apartado anterior)

    for (long i=0; i < 100000L; i++) {
        n = (int)(rnd.nextDouble() * 10.0);
        ndigitos[n]++;
    }

Si n sale cero suma una unidad al contador de ceros, ndigitos[0]. Si n sale uno, suma una unidad al contador de unos, ndigitos[1], y así sucesivamente.

Finalmente, se imprime el resultado, los números que guardan cada uno de los elementos del array ndigitos

    for (int i = 0; i < 10; i++) {
        System.out.println(i+": " + ndigitos[i]);
    }

Observaremos en la consola que cada número 0, 1, 2...9 aparece aproximadamente 10000 veces.

 

Secuencias de números aleatorios

En la siguiente porción de código, se imprime dos secuencias de cinco números aleatorios uniformemente distribuídos entre [0, 1), separando los números de cada una de las secuencias por un carácter tabulador.

    System.out.println("Primera secuencia");
    for (int i = 0; i < 5; i++) {
        System.out.print("\t"+rnd.nextDouble());
    }
    System.out.println("");

    System.out.println("Segunda secuencia");
    for (int i = 0; i < 5; i++) {
        System.out.print("\t"+rnd.nextDouble());
    }
    System.out.println("");

Comprobaremos que los números que aparecen en las dos secuencias son distintos.

En la siguiente porción de código, se imprime dos secuencias iguales de números aleatorios uniformemente distribuídos entre [0, 1). Se establece la semilla de los números aleatorios con la función miembro setSeed.

    rnd.setSeed(3816);
    System.out.println("Primera secuencia");
    for (int i = 0; i < 5; i++) {
        System.out.print("\t"+rnd.nextDouble());
    }
    System.out.println("");

    rnd.setSeed(3816);
    System.out.println("Segunda secuencia");
    for (int i = 0; i < 5; i++) {
        System.out.print("\t"+rnd.nextDouble());
    }
    System.out.println("");
package azar;

import java.util.Random;

public class AzarApp {
  public static void main (String[] args) {
    int[] ndigitos = new int[10];
    int n;
    
    Random rnd = new Random();

// Inicializar el array
    for (int i = 0; i < 10; i++) {
        ndigitos[i] = 0;
    }

// verificar que los números aleatorios están uniformente distribuídos
    for (long i=0; i < 100000L; i++) {
// genera un número aleatorio entre 0 y 9
        n = (int)(rnd.nextDouble() * 10.0);
//Cuenta las veces que aparece un número
        ndigitos[n]++;
    }

// imprime los resultados
    for (int i = 0; i < 10; i++) {
        System.out.println(i+": " + ndigitos[i]);
    }

//Dos secuencias de 5 número (distinta semilla)
    System.out.println("Primera secuencia");
    for (int i = 0; i < 5; i++) {
        System.out.print("\t"+rnd.nextDouble());
    }
    System.out.println("");

    System.out.println("Segunda secuencia");
    for (int i = 0; i < 5; i++) {
        System.out.print("\t"+rnd.nextDouble());
    }
    System.out.println("");

//Dos secuencias de 5 número (misma semilla)
    rnd.setSeed(3816L);
    System.out.println("Primera secuencia");
    for (int i = 0; i < 5; i++) {
        System.out.print("\t"+rnd.nextDouble());
    }
    System.out.println("");

    rnd.setSeed(3816);
    System.out.println("Segunda secuencia");
    for (int i = 0; i < 5; i++) {
        System.out.print("\t"+rnd.nextDouble());
    }
    System.out.println("");
  }
}