“Aleatorio” es fácil de pedir y sorprendentemente fácil de hacer mal. La diferencia entre un generador en el que puedes confiar para una rifa y uno que favorece silenciosamente ciertos números se reduce a unas pocas ideas: de dónde proviene la aleatoriedad, cómo se mapea a tu rango y si necesitas que el sorteo sea impredecible o reproducible. Este generador está construido sobre esas distinciones — criptográficamente seguro por defecto, sin sesgo por construcción, con un modo opcional con semilla para cuando la repetibilidad importa más que el secreto. Las secciones siguientes explican qué ocurre por debajo y cómo elegir la configuración correcta.

Aleatorio verdadero vs. pseudoaleatorio

Hay dos familias de aleatoriedad. Un generador de números aleatorios verdadero (o de hardware) extrae impredecibilidad de un proceso físico — ruido eléctrico, fluctuaciones de temporización, decaimiento radiactivo. Un generador pseudoaleatorio (PRNG) ejecuta una fórmula determinista a partir de una semilla; su salida parece aleatoria y pasa pruebas estadísticas, pero toda la secuencia queda fija una vez que conoces la semilla.

Tu navegador conecta ambos mundos. crypto.getRandomValues —la fuente que usa esta herramienta por defecto— es un PRNG criptográficamente seguro que se resiembra continuamente a partir del pozo de entropía de hardware del sistema operativo. Para efectos prácticos, su salida es impredecible y sin sesgo, por lo que es la herramienta correcta para rifas, tokens de seguridad y cualquier caso donde alguien pudiera beneficiarse adivinando el siguiente valor. El más antiguo Math.random es un PRNG simple sin garantías de seguridad y deliberadamente no se usa aquí.

Sesgo de módulo, y por qué el muestreo por rechazo lo corrige

Este es el error que comete la mayoría del código aleatorio casero. Para convertir un número aleatorio grande en, digamos, un número del 1 al 6, el movimiento obvio es el resto: 1 + (x mod 6). El problema es que la fuente tiene 2³² valores posibles, y 2³² no es divisible entre 6. Los valores sobrantes en la parte superior del rango dan la vuelta y caen en los primeros resultados, haciendo que 1, 2, 3 y 4 sean ligeramente más probables que 5 y 6. Con un dado de seis caras el sesgo es minúsculo; con un rango grande, o a lo largo de millones de sorteos, se vuelve medible — y en contextos de seguridad es una debilidad real.

La solución es el muestreo por rechazo: calcular el múltiplo más grande de tu rango que cabe en 2³², extraer valores sin procesar y descartar los que caigan en el grupo sobrante antes de tomar el resto. Se descartan algunos sorteos, pero cada entero de tu rango termina con exactamente la misma probabilidad. Este generador hace esto para cada entero que produce, así que “1–6” realmente es un dado justo y “1–10,000” realmente es uniforme.

Único vs. repetido, y selecciones justas de lotería

“Permitir repeticiones” extrae con reemplazo: cada elección es independiente, así que el mismo número puede aparecer más de una vez — el modelo correcto para dados y tiradas de moneda. “Único” extrae sin reemplazo: cada valor aparece como máximo una vez, que es lo que quieres para una rifa, un selector de equipos o una línea de lotería. Cuando pides valores únicos, el generador mezcla el conjunto elegible con un shuffle Fisher–Yates parcial y toma los primeros k, lo que mantiene cada combinación con la misma probabilidad y garantiza que no haya duplicados.

Aquí importan dos salvaguardas. No puedes extraer más valores únicos de los que contiene el rango — pedir 10 números únicos del 1 al 6 es imposible, así que la herramienta extrae todos los que puede y te avisa. Y la lista de exclusión elimina valores específicos (un ganador ya sorteado, un 13 de mala suerte) del conjunto antes del sorteo, lo que también reduce el conjunto único.

Cuándo usar una semilla (reproducibilidad)

La mayoría de las veces quieres aleatoriedad que no puedas predecir, así que el modo cripto-seguro por defecto es correcto. Pero a veces quieres lo opuesto: un sorteo que puedas repetir a demanda. Para eso está la semilla. En modo Con semilla, los números provienen de mulberry32, un PRNG determinista, y la misma semilla con la misma configuración siempre produce los mismos números.

Esto es genuinamente útil. Un investigador puede publicar la semilla junto con un estudio para que la muestra aleatoria sea reproducible. El organizador de una rifa puede anunciar la semilla con antelación para que los participantes puedan verificar el sorteo después en lugar de confiar ciegamente. Un desarrollador puede sembrar datos de prueba para que las pruebas fallidas sean repetibles. La contrapartida es que una secuencia con semilla es, por diseño, predecible para cualquiera que conozca la semilla — así que nunca uses el modo con semilla para generar contraseñas, claves o cualquier cosa que deba mantenerse en secreto.

¿Es justo? Leyendo la distribución

“¿Esto es realmente aleatorio?” es una pregunta justa, y la pestaña de Estadísticas está ahí para responderla. Para un solo sorteo pequeño no se puede saber mucho — cinco números del 1 al 100 no se verán espaciados de manera uniforme, y eso es normal; la aleatoriedad verdadera es irregular, no ordenada. El patrón solo emerge a escala. Tira un dado unos cientos de veces, o genera una muestra grande, y las barras de frecuencia se aplanan hacia alturas iguales, que es la firma visual de una distribución uniforme.

Esto también es el antídoto contra la falacia del jugador. Una racha de cinco caras no hace que salga cruz “porque toca” — cada lanzamiento es independiente y sigue siendo 50/50, y el conteo acumulado simplemente se acerca al 50% a medida que crece el número de lanzamientos (la ley de los grandes números), sin que ningún lanzamiento individual esté influenciado por los anteriores.