La respuesta corta
Una computadora sigue instrucciones al pie de la letra, así que no puede crear azar de la nada. O bien calcula números que superan las pruebas estadísticas de aleatoriedad (un generador pseudoaleatorio, PRNG), o bien mide algo físicamente impredecible y lo procesa (una fuente aleatoria real o de hardware). Los sistemas modernos combinan ambas cosas: el sistema operativo reúne ruido impredecible y lo usa como semilla de un PRNG criptográficamente seguro (CSPRNG), que luego produce todos los números que hagan falta.
El generador de esta página usa la fuente segura del navegador mediante la Web Crypto API y convierte el resultado a tu rango sin sesgo. Escribe el Mínimo y el Máximo, elige Cuántos y pulsa Generar.
Pruébalo aquí: Generador de números aleatorios
Abrir la herramienta completaGeneradores pseudoaleatorios y semillas
Un PRNG guarda un estado interno. Cada vez que pides un número, mezcla ese estado con una fórmula fija y devuelve parte del resultado. El diseño clásico más simple, el generador congruencial lineal, calcula el siguiente estado como (a por estado más c) módulo m. Diseños mejores como el Mersenne Twister (el predeterminado del módulo random de Python) o la familia xorshift producen secuencias de mucha más calidad; el Mersenne Twister solo se repite después de 2 elevado a 19.937 menos 1 pasos.
La semilla es el estado inicial. La misma semilla produce siempre la misma secuencia. En muchos casos eso es una ventaja: un científico puede repetir una simulación exacta, un videojuego puede reconstruir un mundo entero a partir de un código corto y una prueba puede reproducir un error. Pero si un programa toma la semilla de algo adivinable, como la hora actual en segundos, un atacante puede probar todas las semillas probables y recrear los números.
Pseudoaleatorio frente a criptográficamente seguro
Los PRNG rápidos de uso general son estadísticamente buenos pero predecibles: tras observar suficientes salidas, se puede reconstruir el estado interno y predecir todos los números siguientes. Eso no importa para un efecto de partículas en un juego, pero sí para una contraseña, un sorteo o un token de seguridad.
| Tipo | De dónde salen los números | ¿Predecible? | Uso típico |
|---|---|---|---|
| PRNG simple (LCG, xorshift, Mersenne Twister) | Una fórmula y una semilla | Sí, a partir de la semilla o de suficientes salidas | Simulaciones, juegos, gráficos |
| CSPRNG | Una fórmula alimentada y renovada con ruido del sistema | No, en la práctica | Contraseñas, claves, sorteos, tokens |
| RNG de hardware | Ruido físico como el térmico o la variación de tiempos | No | Alimentar la reserva del sistema operativo |
Dónde encuentran las computadoras el azar real
Los sistemas operativos recogen pequeños eventos impredecibles: el momento exacto de las interrupciones, la actividad del disco y de la red, y generadores de hardware dedicados, presentes en muchos procesadores modernos, que muestrean ruido eléctrico. Esa entropía se mezcla en una reserva y sirve para inicializar y renovar periódicamente un CSPRNG. Linux la ofrece mediante getrandom y /dev/urandom, y Windows mediante sus funciones de criptografía del sistema.
Algunos servicios van más allá por imagen o por garantía adicional. Random.org usa ruido atmosférico de radio, y Cloudflare es famosa por grabar una pared de lámparas de lava como una de sus fuentes de entropía. Para el uso diario, el generador del sistema operativo ya es lo bastante fuerte para crear claves de cifrado.
Cómo genera el navegador números aleatorios seguros
JavaScript tiene dos opciones. Math.random() devuelve un número entre 0 y 1 a partir de un PRNG rápido (los motores actuales usan algoritmos de tipo xorshift). Sirve para animaciones, pero no está pensado para ser impredecible y la especificación no promete ninguna seguridad.
crypto.getRandomValues() llena un arreglo con bytes aleatorios del CSPRNG del navegador, alimentado por el sistema operativo. Está en todos los navegadores modernos, funciona sin conexión y es lo que deben usar los generadores de contraseñas y el código que crea claves. Cada llamada devuelve como máximo 65.536 bytes, así que los trabajos grandes la llaman varias veces. Este generador, igual que la moneda, los dados, la ruleta y el sorteo de nombres de Anyfeat, usa crypto.getRandomValues.
Por qué rand() % n puede tener sesgo
Un generador te da valores en bruto dentro de un rango fijo, por ejemplo un byte del 0 al 255. La forma obvia de obtener un número del 0 al 5 es tomar el resto de dividir entre 6 (valor % 6). El problema: 256 valores no se reparten por igual en 6 grupos. 256 es 42 por 6 más 4, así que los restos del 0 al 3 aparecen 43 veces cada uno y los restos 4 y 5 solo 42 veces. Algunos resultados son alrededor de un 2,4% más probables que otros. Esto se llama sesgo del módulo.
Con valores de 32 bits y un rango pequeño el sesgo es mínimo, pero con rangos grandes crece. La solución estándar es el muestreo por rechazo: busca el mayor múltiplo de n que cabe en el rango en bruto (252 en el ejemplo del byte), descarta cualquier valor igual o superior y vuelve a sacar otro. Los valores que quedan se reparten por igual en el rango. Este generador saca valores de 32 bits y rechaza la parte desigual, así que cada número de tu rango tiene exactamente la misma probabilidad.
Un error parecido es usar Math.floor(Math.random() * n) cuando hay seguridad en juego. El redondeo está bien para la mayoría de los rangos, pero la fuente es predecible, así que no debe usarse para contraseñas ni para sorteos con dinero de por medio.
Números sin repetir, mezclas y errores frecuentes
- Números sin repetir: para sacar números sin repeticiones, mezcla todo el rango con el algoritmo de Fisher Yates y toma los primeros k, o saca números y descarta los repetidos. Este generador hace exactamente eso con Sin repetir marcado y te avisa si el rango es demasiado pequeño para la cantidad.
- Mezclas sesgadas: ordenar una lista con una función de comparación aleatoria no da una mezcla uniforme. Usa Fisher Yates.
- Sembrar demasiado a menudo: dar la hora como semilla a un PRNG dentro de un bucle puede producir el mismo número muchas veces seguidas.
- Decimales: elegir un decimal escalando una fracción aleatoria puede hacer menos probables los extremos. Esta herramienta, en cambio, saca un número entero de pasos (con 2 decimales, centésimas) para que ambos extremos entren con la misma probabilidad.
- Esperar que no haya patrones: una salida realmente aleatoria tiene rachas y repeticiones. Ver un 7 dos veces seguidas no indica que el generador esté roto.