01 · Punto de partida
El dado, el índice y el sorteo
Elegir carta, cara, índice de bootstrap o posición de Fisher-Yates pide enteros equiprobables. El método es una línea, pero el 90 % de los sesgos discretos nace de escribirla mal: redondear en vez de truncar, o tomar módulo sobre un rango no divisor.
Este tema fija la fórmula canónica y sus momentos para auditarla.
- ¿Por qué piso y no redondeo?
- ¿Qué media y varianza debe dar {1,…,n}?
- ¿Cómo incluir ambos bordes a y b?
- ¿Cuándo el módulo % sesga?
02 · Definición
Masa plana y escalera regular
P(X = k) = 1/n, F con n saltos iguales de 1/n. E[X] = (a+b)/2, Var(X) = (n²−1)/12.
Piso exacto
⌊n·U⌋ parte [0,n) en n intervalos [k,k+1) de largo 1. Desplazar por a incluye ambos bordes.
Bordes inclusivos
U ∈ [0,1) ⇒ n·U ∈ [0,n) ⇒ X ∈ {a,…,b}. El b sale con prob. 1/n; nunca sale b+1.
O(1) puro
Una multiplicación + un piso por muestra. Base de alias (elegir columna) y Fisher-Yates (elegir posición).
| Código | Soporte real | Problema |
|---|---|---|
1+int(6*U) | {1…6} × 1/6 | Correcto |
1+round(5*U) | {1…6} desigual | Bordes a mitad de peso |
int(U*2**32) % 6 | Sesgo si 2³² mod 6 ≠ 0 | Resto no divide parejo |
03 · Anatomía
Piso, módulo y rangos grandes
- Piso, no redondeo
roundcrea n+1 valores efectivos con extremos a mitad.int()trunca hacia cero (= piso en positivos): correcto aquí.- Módulo con resto
randbits(k) % nes uniforme solo si n divide a 2ᵏ. Si no, rechazar valores ≥ mayor múltiplo de n (método de Lemire).- Rangos grandes
- Con n > 2⁵³, n·U en doble pierde resolución (enteros no representables). Usar enteros aleatorios nativos (
randbelow) en vez de flotante. - Índices 0-based
- Para listas:
int(n*U)en {0…n−1}. Sumar 1 solo si el modelo es 1-based (dados).
Piso escalado
Exacto en flotante normal
Para n ≤ 2²⁰ el error de borde es despreciable y la frecuencia calza a 1/n con N grande.
Módulo ingenuo
Sesgo sistemático
Con 2³² valores y n = 6 sobran 4: los restos 0–3 salen una vez de más. Rechazar el excedente lo corrige.
04 · Dónde se usa un entero justo
Del dado al índice bootstrap
- 1Dados y sorteos.
Juegos, pasos aleatorios, decisiones equiprobables.
- 2Índices.
Elegir fila, columna de alias (Tema 13) o posición de Fisher-Yates (Tema 33).
- 3Bootstrap.
Remuestrear índices 0…n−1 con reemplazo. (Temas 30, 34)
- 4Discretización consciente.
Si necesitás bines, el piso es el binner; el redondeo es otro modelo.
05 · Representación en Python
Dado canónico y auditoría de momentos
Implementación directa más chequeo de media/varianza contra (a+b)/2 y (n²−1)/12.
Python en tu navegador. Probá n = 20: la varianza teórica es 33,25.
import random
random.seed(130)
a, b = 1, 6
n = b - a + 1
N = 12000
def uniforme_discreta(a, b):
return a + int((b - a + 1) * random.random())
m = [uniforme_discreta(a, b) for _ in range(N)]
media = sum(m) / N
var = sum((x - media) ** 2 for x in m) / N
print("media:", round(media, 3), "teórica:", (a + b) / 2)
print("var:", round(var, 3), "teórica:", round((n**2 - 1) / 12, 3))
print("frec:", [round(m.count(v) / N, 3) for v in range(a, b + 1)])
Dado: media ≈ 3,5, var ≈ 2,917, seis ≈ 0,167. Con round los bordes caerían a ~0,08.
06 · Exploración
Laboratorio: planicie discreta de n caras
Movete n y N. Las barras deben pegarse a la línea 1/n. Con N chico hay ruido; con N grande, planicie.
Dado de n caras
X = 1 + ⌊n·U⌋
Con n 6 y N 6000, planicie en 0,167.
Barras 1…n vs línea teórica. Probá n = 12 con N = 200 (ruido) y N = 12000 (plano).
Preguntas para explorar
- Con n = 6, ¿qué frecuencia y media esperás?
- Con n = 2, ¿a qué Bernoulli equivale? ¿Con qué p?
- Si ves una cara sistemáticamente baja con N = 12000, ¿ruido o sesgo?
Ver respuestas sugeridas
- 1/6 ≈ 0,167 y media 3,5.
- A Bernoulli(0,5): 1 + ⌊2U⌋ vale 1 o 2 equiprobables.
- Sesgo probable: con N = 12000 el error típico por cara es ~0,004; desvíos mayores delatan método.
07 · Comprensión
Confusiones frecuentes
«Redondear es lo mismo que truncar»
No: round crea n+1 puntos efectivos y afina bordes. Piso reparte 1/n exacto.
«% n siempre es uniforme»
Solo si el rango base es múltiplo de n. Si no, rechazar el excedente (rejection sampling en miniatura).
«a + int((b−a)*U) incluye b»
No: falta el +1. Sin él, b nunca sale y el rango efectivo es {a…b−1}.
«Con n enorme da igual el método»
Con n > 2⁵³ el flotante no resuelve enteros: usar enteros aleatorios nativos, no n·U en doble.
08 · Práctica guiada
Ejercicios con Python
Ejercicio 1: dado auditado
Dado {1…6}, N = 12000, semilla 131: verificá seis ≈ 0,167, media 3,5 y var 2,917.
import random
random.seed(131)
N = 12000
m = [1 + int(6 * random.random()) for _ in range(N)]
media = sum(m) / N
print([round(m.count(v) / N, 3) for v in range(1, 7)])
print(round(media, 3), round(sum((x-media)**2 for x in m)/N, 3))
Ver solución razonada
Frecs 0,16–0,17, media ≈ 3,5, var ≈ 2,9. Desvíos mayores con N = 12000 ya huelen a bug.
Ejercicio 2: cazar el redondeo
Compará 1+int(6U) vs 1+round(5U) con 20000 tiros. ¿Qué caras se deforman?
import random
random.seed(132)
N = 20000
bien = [1 + int(6 * random.random()) for _ in range(N)]
random.seed(132)
mal = [1 + round(5 * random.random()) for _ in range(N)]
print("bien:", [round(bien.count(v)/N, 3) for v in range(1, 7)])
print("mal: ", [round(mal.count(v)/N, 3) for v in range(1, 7)])
Ver solución
Bien plano; mal con centro alto y bordes bajos (o patrón según round-half). El histograma lo delata.
Ejercicio 3: índice bootstrap
Con datos de 50 elementos, remuestreá 2000 índices {0…49} y verificá que cada uno sale ≈ 0,02.
Ver una posible respuesta
import random
random.seed(133)
n, N = 50, 2000
idx = [int(n * random.random()) for _ in range(N)]
print("min frec:", round(min(idx.count(v)/N for v in range(n)), 4),
"max frec:", round(max(idx.count(v)/N for v in range(n)), 4))
Mín ≈ 0,012, máx ≈ 0,028 con N = 2000: banda de ruido esperable alrededor de 0,02.
09 · Síntesis
Ideas para recordar
- U{a…b} = a + ⌊(b−a+1)·U⌋: piso, no redondeo, bordes inclusivos.
- Media (a+b)/2, varianza (n²−1)/12 para auditar.
- % n solo si divide al rango base; si no, rechazar excedente.
- n enorme ⇒ enteros nativos, no flotante.
- Base de alias, índices y Fisher-Yates.
En el próximo tema contaremos fracasos hasta el éxito: la geométrica.