Inicio · Parte 01 — Aritmética computacional y representación numérica
ε = 2⁻⁵² ≈ 2.22e−16 (float64)
ulp(x) ≈ ε · 2^⌊log₂|x|⌋
El epsilon de máquina se define como el menor ε tal que 1 + ε ≠ 1 en la aritmética del formato. En float64 vale exactamente 2⁻⁵², porque la mantisa tiene 52 bits almacenados: sumar algo menor que el último bit de la mantisa no cambia el número. El laboratorio comprueba justamente eso: 1.0 + ε difiere de 1.0, pero 1.0 + ε/2 no.
El ULP —unit in the last place— es el concepto relacionado pero distinto: la distancia entre un float concreto y su vecino inmediato. No es constante: cerca de 1 vale unos 2.2·10⁻¹⁶, cerca de 10⁶ vale unos 1.2·10⁻¹⁰, y cerca de 10⁻⁶ vale unos 2.1·10⁻²². Los floats no están repartidos uniformemente en la recta: se concentran cerca del cero y se espacian al alejarse.
Esta no uniformidad explica un fenómeno cotidiano: sumar un número muy pequeño a uno muy grande no cambia nada. 1e16 + 1.0 devuelve 1e16 porque 1.0 es menor que el ULP en esa escala. No es un redondeo agresivo: es que el resultado exacto no tiene representación y el más cercano es el propio 1e16.
Medir un error en ULP en lugar de en unidades absolutas es la forma correcta de evaluar la calidad de una función numérica. Una implementación de sin «correctamente redondeada» tiene un error menor a 0.5 ULP; una aceptable, menor a 1 ULP. Esa es la unidad en la que las bibliotecas matemáticas declaran su precisión.
Epsilon, ULP y el límite de la suma.
ε = sys.float_info.epsilon = 2.220446049250313e−16 = 2⁻⁵²
1.0 + ε ≠ 1.0 ✓ (por definición de ε)
1.0 + ε/2 == 1.0 ✓ (por debajo del último bit)
ULP según la magnitud:
ulp(1.0) = 2.22e−16
ulp(1e6) = 1.16e−10 500 000 veces mayor
ulp(1e−6) = 2.12e−22
Siguiente float tras 1.0: 1.0000000000000002
Los floats no son un retículo uniforme: son casi logarítmicos.
Machine epsilon y la distancia al float siguiente.
python classes/part-01-aritmetica-computacional-y-representacion-numerica/031-ulp-y-machine-epsilon/lab.py
compmath run 031
sys.float_info.epsilon2**-521.0 + eps != 1.01.0 + eps/2 == 1.0ulp_en_1.0ulp_en_1e6ulp_en_1e-6siguiente_float_tras_1.0{
"sys.float_info.epsilon": 2.220446049250313e-16,
"2**-52": 2.220446049250313e-16,
"1.0 + eps != 1.0": true,
"1.0 + eps/2 == 1.0": true,
"ulp_en_1.0": 2.220446049250313e-16,
"ulp_en_1e6": 1.1641532182693481e-10
}
Elegir tolerancias, evaluar la calidad de una biblioteca matemática y entender por qué un acumulador pierde términos pequeños. Es el prerrequisito de las clases 032 y 034.
float32, bfloat16 y la cuantización a int8 son decisiones de representación. Los NaN en un entrenamiento casi siempre nacen aquí, no en la arquitectura.
9783319765266 verificado en International ISBN Agency (2026-08-19).math.ulp y math.nextafter — documentación de la herramienta que ejecuta el laboratorio · URL de la fuente primaria comprobada en Python Software Foundation (2026-08-19).