Generador de números pseudoaleatorios

Programa generador de números pseudoaleatorios en Java.

generador-de-numeros-pseudoaleatorios

¿Qué es un GNA?

Un GNA (Generador de Números Aleatorios o Random Number Generator) es un programa que genera números de forma aleatoria. En informática, comúnmente se emplean algoritmos pseudoaleatorios, los cuales producen secuencias de números que parecen aleatorios pero son generados mediante un cálculo determinista a partir de una semilla (un valor inicial). Esto significa que, dado el mismo valor inicial, el algoritmo generará siempre la misma secuencia.

Uno de los algoritmos pseudoaleatorios más ampliamente utilizados es el Método Congruencial Lineal (o variantes del método congruencial). En este artículo, exploraremos una modificación del método congruencial. Se generarán tres números congruenciales: el primero servirá como indicador para determinar cuál de los otros dos utilizar.

Semillas que pasan los tests

Para evaluar si un algoritmo pseudoaleatorio es adecuado, existen varias pruebas estadísticas diseñadas para medir qué tan bien imita el comportamiento de números verdaderamente aleatorios. En nuestro ejemplo, el algoritmo propuesto ha sido evaluado mediante pruebas como:

  • Test de Frecuencias: verifica si los números generados tienen una distribución uniforme.
  • Test de Series: evalúa si las parejas de números consecutivos son uniformemente distribuidas.
  • Test GAP: mide la separación entre apariciones de ciertos valores en la secuencia.
  • Prueba de Yule-Walker: analiza propiedades de autocorrelación en la secuencia.
  • Prueba de Distancias: mide la distancia euclidiana entre puntos generados en un espacio n-dimensional.
  • Autocorrelación: evalúa la dependencia entre números en diferentes posiciones de la secuencia (en este caso, la mayoría de las pruebas fueron satisfactorias).
  • Kolmogorov-Smirnov: compara la distribución acumulada de los números generados con la distribución teórica esperada.
  • Maxmin-up y Maxmin-down: analizan las oscilaciones y extremos locales en la secuencia.

Dado que el algoritmo pasó la mayoría de estas pruebas con resultados satisfactorios, podemos considerarlo razonablemente bueno para generar números pseudoaleatorios en contextos donde la aleatoriedad no necesita ser perfecta.

A continuación se muestra un conjunto de 5 semillas que pasaron los tests:

c1 = new congruencial(2147483647,8363,13259,45646);
c2 = new congruencial(2147483647,94781,52859528,4420567);
c3 = new congruencial(2147483647,86341,33107542,33107);
c1 = new congruencial(2147483647,2441,19183,437693);
c2 = new congruencial(2147483647,403681,486641,42773);
c3 = new congruencial(2147483647,449851,611549,14087);
c1 = new congruencial(2147483647,2441,19183,437693);
c2 = new congruencial(2147483647,548489,486641,42773);
c3 = new congruencial(2147483647,562753,611549,611953);
c1 = new congruencial(2147483647,376891,19183,437693);
c2 = new congruencial(2147483647,548489,486641,467353);
c3 = new congruencial(2147483647,562753,611549,611953);
c1 = new congruencial(2147483647,3498013,3552463,437693);
c2 = new congruencial(2147483647,4050589,3938927,3722491);
c3 = new congruencial(2147483647,3621617,3574819,3498419);

Programa generador de números pseudoaleatorios en Java

Este programa genera una secuencia de 3000 números pseudoaleatorios. Para obtener distintas tiras de números basta con cambiar las semillas que se han especificado anteriormente.

public class Composite {
private congruencial c1;
private congruencial c2;
private congruencial c3;
private double [] vector;
private int index;
public Composite() {
index = 0;
c1 = new congruencial(2147483647,8363,13259,45646);
c2 = new congruencial(2147483647,94781,52859528,4420567);
c3 = new congruencial(2147483647,86341,33107542,33107);
vector = new double[3000];
for (int i=0; i < vector.length; i++){
vector[i] = c1.next();
}
}
public double next(){
if(vector[index] > 0.5){
return c2.next();
} else {
return c3.next();
}
}
public congruencial getC1() {
return c1;
}
public congruencial getC2() {
return c2;
}
public congruencial getC3() {
return c3;
}
class congruencial {
private int m;
private int a;
private int c;
private int seed;
private double prev=0;
public congruencial(int m, int a, int c, int seed){
this.m = m;
this.a = a;
this.c = c;
this.seed = seed;
}
public double next() {
prev = (a * prev + c )%m;
return prev/m;
}
}
public static void main(String [] args){
Composite composite = new Composite();
for (int i=0; i < 3000; i++){
System.out.println(composite.next());
}
}
}

Si deseamos usar este algoritmo en otros programas podemos utilizar la función next() que nos devuelve el siguiente número de la tira generada.