Números Pseudoaleatorios · Tema 13

Parámetros de un generador congruencial

Qué rompe cada letra de (a, c, m) cuando se elige mal y qué guía práctica usar para no fabricar un RANDU casero.

01 · Punto de partida

La misma fórmula, destinos opuestos

En el Tema 12 iteraste (5·x+3) mod 16 (período 16) y (4·x+2) mod 16 (período ≤ 4). Misma receta, mismo m, una letra distinta y un generador sirve y el otro es basura. La diferencia no es suerte: son los parámetros.

Este tema disecciona m, a, c y la semilla: qué decide cada uno, qué fallos típicos producen y qué checklist aplicar antes de adoptar un trío.

  • ¿Qué tamaño de m necesito para mi N?
  • ¿Por qué c debe ser coprimo con m?
  • ¿Por qué a = 4 colapsa y a = 5 funciona con m = 16?
  • ¿Cómo verifico overflow antes de portar a C?

02 · Rol de cada uno

Quién manda qué

◈

Módulo m

Techo del período (≤ m) y costo del mod. Potencia de 2 = rapidísimo pero bits bajos débiles; primo grande = mejor estadística y mod más caro.

⇄

Incremento c

El «empujón» que evita puntos fijos. Para período completo debe ser coprimo con m (sin divisor común). Con m potencia de 2: c impar.

▣

Multiplicador a

La mezcla. Controla período y estructura multidimensional (pares/triplas). Con m = 2ᵏ se exige a ≡ 1 mod 4; además conviene a ni tiny ni pegado a m.

Fallos típicos por parámetro.
ParámetroError típicoSíntoma
m chicom = 16 para N = 10 000Vueltas calcadas, histograma de picos
c con divisor comúnm = 16, c = 2 o 4Período ≤ 8 aunque a sea bueno
a maloa = 4 con m = 16; 65539 con 2³¹Ciclo corto o triplas en planos
Overflowa·(m−1) > 2³² en C 32 bitsSecuencia distinta a la teórica

03 · Guía práctica

Checklist antes de adoptar

1. m según N
Pedí m ≫ N (ideal m > 1000·N). Si N es millonario, m = 2³¹ queda corto: migrá a moderno (Tema 17).
2. c coprimo
mcd(c, m) = 1. Con m = 2ᵏ: c impar. Con c = 0 aceptás techo m−1 y semilla ≠ 0.
3. a con teoría
Con m = 2ᵏ: a mod 4 = 1 y a lejos de 1 y de m. Nunca «redondo por velocidad» estilo RANDU sin validar espectro.
4. Overflow
Verificá a·(m−1) + c entra en tu entero (64 bits o Schrage). Lo que en Python anda, en C puede desbordar.

Trío sano (m = 16)

(5, 3): período 16

c impar, a mod 4 = 1: cumple el checklist y recorre todo el anillo.

Trío roto (m = 16)

(4, 2): período ≤ 4

c par y a mod 4 = 0: viola todo y colapsa a un rincón del anillo.

04 · Ejemplos

Un dígito cambia todo

(a,c,m)→Chequear→Período real
  1. 1
    (5,3,16): completo.

    16 estados, histograma parejo en N = 64 con 4 vueltas.

  2. 2
    (5,2,16): roto por c.

    c par comparte factor 2 con 16: el ciclo se parte.

  3. 3
    (4,3,16): roto por a.

    a mod 4 = 0: aunque c sea impar, no recorre todo.

  4. 4
    (16807,0,2³¹−1): clásico.

    Multiplicativo con primo: período m−1 si a es raíz primitiva. Semilla ≠ 0.

05 · Barrido en Python

Probar tríos en miniatura

Con m chico podés barrer y ver el patrón que la teoría resume. Con m real no barres: aplicás el teorema.

Python en tu navegador. Barrete a 1–15 con (c=3,m=16) y anotá cuáles dan 16.

def periodo(a, c, m, semilla=7):
    visto = set()
    x = semilla
    while x not in visto:
        visto.add(x)
        x = (a * x + c) % m
    return len(visto)


for a in range(1, 16):
    print(a, periodo(a, 3, 16))

Verás 16 solo en a = 1, 5, 9, 13 (los ≡ 1 mod 4): el patrón que el laboratorio confirma.

Chequear overflow

def entra(a, c, m, bits=32):
    return a * (m - 1) + c < 2**bits


print(entra(16807, 0, 2**31 - 1, 32))
print(entra(65539, 0, 2**31, 32))

06 · Exploración

Laboratorio: qué rompe cada letra

Fijá m y mové a, c. El semáforo chequea c impar y a mod 4 = 1 (para m potencia de 2). El canvas muestra la secuencia y el panel el período real.

EXPERIMENTO 13

Checklist en vivo

c impar · a ≡ 1 (mod 4)

Los resultados numéricos aparecen debajo.
c impar—
a mod 4 = 1—
Período—
¿Completo?—

Con (5,3,16) ambas luces en verde y p = 16.

Luces verdes + período = m: trío sano. Alguna roja + período corto: letra culpable a la vista.

Preguntas para explorar

  1. Dejá a = 5 y poné c = 2: ¿qué luz se apaga? ¿p?
  2. Dejá c = 3 y poné a = 4: ¿qué luz se apaga? ¿p?
  3. Con m = 32, buscá un trío completo distinto de (5,3). ¿Qué patrón cumplen los a que funcionan?
Ver respuestas sugeridas
  1. Se apaga c impar; p se parte (≤ 8). El par comparte el factor 2 con 16.
  2. Se apaga a mod 4; p colapsa (≤ 4–8). El multiplicador no mezcla.
  3. Funcionan 1, 5, 9, 13, 17…: todos ≡ 1 mod 4. Es el patrón que el Tema 14 demuestra.

07 · Comprensión

Confusiones frecuentes

«m grande compensa a y c malos»

No: con m = 2³² y (4,2) sigues atrapado en un rincón minúsculo del anillo. El tamaño no cura la aritmética.

«a grande = mezcla mejor»

Un a pegado a m o con mala estructura espectral es peor que uno moderado validado. Grande no es criterio.

«c = 0 da período m»

Con c = 0 el 0 queda fuera del ciclo útil: el techo es m−1 y solo si a es raíz primitiva (primo) o cumple condiciones (potencia de 2 con restricciones).

«Cambio la semilla y zafa»

La semilla no toca el largo del ciclo ni la estructura. Si el trío es malo, todas las semillas son malas.

08 · Práctica guiada

Ejercicios con Python

Ejercicio 1: el culpable c

Fijá a = 5, m = 16 y barrete c 0–7. ¿Cuáles dan período 16?

def periodo(a, c, m, s=7):
    v = set()
    x = s
    while x not in v:
        v.add(x)
        x = (a * x + c) % m
    return len(v)


for c in range(8):
    print(c, periodo(5, c, 16))
Ver solución razonada

Solo los impares dan 16: los pares comparten factor 2 con 16 y parten el ciclo. Es mcd(c,m)=1 en acción.

Ejercicio 2: el culpable a

Fijá c = 3, m = 16 y barrete a 1–8. ¿Qué patrón ves?

for a in range(1, 9):
    print(a, periodo(a, 3, 16))
Ver solución

16 solo en 1 y 5 (≡ 1 mod 4). El resto cae a 8, 4 o 2. Un dígito en a decide todo.

Ejercicio 3: overflow antes de portar

¿Entra 1103515245·(2³¹−1) (glibc) en 64 bits? ¿Y en 32?

Ver una posible respuesta
a, m = 1103515245, 2**31
print(a * (m - 1) < 2**64)
print(a * (m - 1) < 2**32)

En 64 sí, en 32 no: por eso glibc trunca a 32 bits por diseño (y por eso sus bits bajos son débiles). Saberlo evita «bugs» que son especificación.

09 · Síntesis

Ideas para recordar

  • m: techo y costo; c: coprimo para alcanzar el techo; a: mezcla y estructura.
  • Con m = 2ᵏ: c impar y a ≡ 1 mod 4 para período completo.
  • Semilla no compensa trío malo; m grande tampoco.
  • Verificá overflow: a·(m−1)+c vs. tu entero.
  • Período completo es piso; la calidad fina se testea.

En el próximo tema formalizaremos el techo: el período máximo y el teorema de Hull–Dobell que lo garantiza.