Tu país

Las herramientas que lo admiten usan tu país para la moneda local, el formato de los números, las unidades y el tamaño del papel. Tu elección se guarda solo en este navegador.

Escribe un nombre o un código de dos letras. Usa las flechas arriba y abajo para recorrer los países, Intro para elegir uno y Escape para cerrar.

Python  Módulo 2 – Valores, variables, números y cadenas

Sorpresas del punto flotante y cómo manejarlas

Por qué 0.1 + 0.2 no es 0.3 en Python, cómo se guardan los floats en binario y cómo compararlos, sumarlos y redondearlos con math.isclose, fsum y Decimal.

Gratis: 15 minutos

Qué vas a aprender

  • Explicar por qué 0.1 + 0.2 != 0.3 con la representación binaria
  • Predecir dónde deja un float de guardar números enteros exactos, y qué pasa más allá de su mayor valor
  • Comparar floats de forma segura con math.isclose, y detectar NaN e infinito
  • Sumar muchos floats con precisión y convertir un resultado float en un número entero sin perder una unidad
  • Elegir entre float, decimal.Decimal y fractions.Fraction

Antes de empezar

Qué vas a aprender · Antes de empezar

Qué vas a aprender

  • Explicar por qué 0.1 + 0.2 != 0.3 con la representación binaria
  • Predecir dónde deja un float de guardar números enteros exactos, y qué pasa más allá de su mayor valor
  • Comparar floats de forma segura con math.isclose, y detectar NaN e infinito
  • Sumar muchos floats con precisión y convertir un resultado float en un número entero sin perder una unidad
  • Elegir entre float, decimal.Decimal y fractions.Fraction

Antes de empezar

En esta página

Pide a Python 0.1 + 0.2 y responde 0.30000000000000004. No hay nada roto: C, Java y casi todos los demás lenguajes guardan esos números igual y obtienen el mismo resultado. En cuanto sabes lo que guarda de verdad un float, las sorpresas se vuelven previsibles, y unos pocos hábitos las mantienen fuera de tus resultados.

Vas a ver el valor exacto detrás de 0.1, seguir 0.1 + 0.2 desde el código hasta la respuesta impresa y adquirir los hábitos que mantienen honrados a los floats: comparar con una tolerancia, sumar con fsum(), redondear en lugar de truncar y elegir Decimal o Fraction cuando un float es el tipo equivocado.

Un float guarda la fracción binaria más cercana

En casi todas las computadoras, un float de Python es un número de “doble precisión” IEEE 754: El estándar de aritmética de punto flotante que siguen casi todas las computadoras. Un float de Python es su doble de 64 bits, una fracción binaria con 53 bits significativos y un exponente.: una fracción binaria con 53 bits significativos y un exponente. Las cifras binarias después del punto representan mitades, cuartos, octavos, etc., así que una fracción solo se puede guardar exacta si es una suma de esas piezas, lo que significa que su denominador, en su forma irreducible, es una potencia de 2. 0.75 es ½ + ¼ y es exacto. 0.1 es 1/10, y 10 tiene un factor 5, así que en binario nunca termina: 0.000110011001100… El float conserva los 53 primeros bits significativos y redondea el resto.

Los valores detrás de 0.1, 0.2 y 0.3 Python · stored_value.py
from decimal import Decimal

print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(0.5 + 0.25 == 0.75)  # halves and quarters are exact in binary

print(Decimal(0.1))  # the exact value stored for 0.1
print(Decimal(0.2))
print(Decimal(0.3))
print((0.1).as_integer_ratio())  # the same stored value as a fraction
print(2 ** 55)

Salida

0.30000000000000004
False
True
0.1000000000000000055511151231257827021181583404541015625
0.200000000000000011102230246251565404236316680908203125
0.299999999999999988897769753748434595763683319091796875
(3602879701896397, 36028797018963968)
36028797018963968

Salida registrada con Python 3.14.8 en macOS 26 arm64. Para ejecutarlo tú: mise exec python@3.14.8 -- python3 stored_value.py

Convertir un float a Decimal muestra todas las cifras del valor que guarda. El float de 0.1 es un poco más que 0.1, el de 0.2 un poco más que 0.2, y el de 0.3 un poco menos que 0.3. Como fracción, as_integer_ratio() muestra que el 0.1 guardado es 3602879701896397 dividido entre 2 elevado a 55. Cuando Python imprime un float elige el decimal más corto que se guardaría como el mismo float, y por eso print(0.1) muestra solo 0.1 y el error queda oculto hasta que un cálculo lo saca a la vista.

Conversor de punto flotante IEEE 754 (en inglés) Escribe 0.1 para ver sus 64 bits, el valor exacto guardado y el error de redondeo.

Más de cerca: por qué la suma falla

Entre dos floats vecinos no hay ningún otro float, así que cada resultado tiene que caer en uno de ellos. La suma de los 0.1 y 0.2 guardados cae exactamente a medio camino entre los dos floats más cercanos a 0.3:

A medio camino entre dos floats Python · halfway.py
import math
from fractions import Fraction

exact_sum = Fraction(0.1) + Fraction(0.2)  # the sum of the two stored values, exactly
below = Fraction(0.3)  # the float that 0.3 is stored as
above = Fraction(math.nextafter(0.3, 1))  # the next float up

print(below < exact_sum < above)
print(exact_sum - below == above - exact_sum)  # exactly halfway
print((0.3).hex(), (0.1 + 0.2).hex())  # the last digits: 3 is odd, 4 is even

Salida

True
True
0x1.3333333333333p-2 0x1.3333333333334p-2

Salida registrada con Python 3.14.8 en macOS 26 arm64. Para ejecutarlo tú: mise exec python@3.14.8 -- python3 halfway.py

La suma exacta de los 0.1 y 0.2 guardados queda a medio camino entre los dos floats más cercanos a 0.3 y se redondea hacia arriba, al de arriba.Los dos float más cercanos a 0.3lo que da 0.1 + 0.20.30000000000000004441…un empate: se redondea alfloat cuyo último bit es parla suma exacta de lo guardadopara 0.1 y 0.2: justo en medio0.3 exactocómo se guarda 0.30.29999999999999998889…

Por qué 0.1 + 0.2 cae en el float por encima de 0.3

Descripción en texto del diagrama

Un tramo corto de la recta numérica, dibujado en vertical con los valores mayores más arriba, muestra dos floats vecinos, los más cercanos a 0.3. No hay ningún float entre ellos.

  • El de abajo, 0.29999999999999998889…, es el float en el que se guarda 0.3: es el float más cercano a 0.3, que queda un poco por encima.
  • El de arriba, 0.30000000000000004441…, es el siguiente float hacia arriba.
  • La suma exacta de los valores guardados de 0.1 y 0.2 queda exactamente a medio camino entre los dos. La suma tiene que redondearla a uno de ellos, y un empate va al float cuya última cifra binaria es par, que aquí es el de arriba: una flecha sube la suma hasta él.

Así que 0.1 + 0.2 da el float de arriba, y 0.3 se guarda como el de abajo: dos floats distintos, y por eso 0.1 + 0.2 == 0.3 es False.

En un empate, el hardware redondea al float cuya última cifra binaria es par, la regla por defecto de IEEE 754 y la misma regla de “redondeo al par: La regla que sigue round() con los empates. Un valor exactamente a medio camino entre dos números enteros va al par, así que round(2.5) es 2 y round(3.5) es 4. Más en “Enteros, floats y operadores aritméticos” (en inglés)” que usa round(). Las formas hexadecimales impresas arriba terminan en 3 y en 4, y la par es la del float de arriba. 0.3 escrito en tu programa se guarda como el de abajo, el float más cercano a 0.3. Dos floats distintos, así que == dice False. Sigue el recorrido completo de la suma, etapa por etapa, desde los dos literales de tu código hasta la respuesta que imprime Python:

Interactivo · etapa por etapa 0.1 + 0.2, de tu código a la respuesta impresa Recorre las cinco etapas por las que pasa una suma de floats. Cada paso nombra el valor en esa etapa, y el último lo compara con el literal 0.3.
0.1 + 0.2, de tu código a la respuesta impresa, paso 6 de 6. Se ve: 0.1 + 0.2 en tu código, Cada uno redondeado (0.1000000000000000055…), La suma exacta (a medio camino entre dos floats), La suma redondeada (0.3000000000000000444…), Printed. Resaltados: Cada uno redondeado, La suma redondeada.0.1 + 0.2 en tu códigodos literales decimalesCada uno redondeado0.1000000000000000055…La suma exactaa medio camino entre dos floatsLa suma redondeada0.3000000000000000444…Printedel decimal más corto que encaja0.3 se guarda como el float de abajo

El dibujo muestra la escena completa; sus 6 pasos aparecen abajo.

Todos los pasos en texto
  1. Dos literales. Escribes 0.1 + 0.2. Python lee cada literal como texto decimal y tiene que guardarlo como una fracción binaria con 53 bits significativos.
  2. Cada literal se redondea. 0.1 es 1/10, y 10 tiene un factor 5, así que sus cifras binarias nunca terminan. Python conserva el valor de 53 bits más cercano, un poco más que 0.1, y 0.2 también se guarda un poco alto.
  3. La suma exacta. La suma calcula primero la suma exacta de los dos valores guardados. Cae exactamente a medio camino entre dos floats vecinos, y entre esos dos no hay ningún float.
  4. Un empate va al par. El resultado tiene que ser uno de los dos floats, así que el empate se resuelve con la regla de IEEE 754, hacia el float cuya última cifra binaria es par. Aquí es el de arriba.
  5. El decimal más corto. Para imprimir un float, Python elige el decimal más corto que se guardaría como el mismo float. Para esta suma hacen falta 17 cifras, 0.30000000000000004.
  6. Por qué == dice False. El literal 0.3 solo pasa por las dos primeras etapas y se guarda como el float justo por debajo de la suma. Dos floats distintos no son iguales, así que 0.1 + 0.2 == 0.3 es False.

Punto de control

Comprueba: lo que guarda un float

  1. Pregunta 1 de 2 0.5 + 0.25 == 0.75 es True, pero 0.1 + 0.2 == 0.3 es False. ¿Qué marca la diferencia?

    Elige una respuesta.

    Ver la respuesta: pregunta 1 de 2

    Respuesta: 0.5, 0.25 y 0.75 son sumas de mitades y cuartos, así que se guardan exactos, y su suma también

    Una fracción es exacta en binario solo cuando su denominador, en su forma irreducible, es una potencia de 2. ½, ¼ y ¾ lo son; 1/10, 1/5 y 3/10 no, así que sus floats llevan pequeños errores, y la suma de los floats de 0.1 y 0.2 cae en un float distinto del de 0.3.

  2. Pregunta 2 de 2 Decimal(0.1) muestra 0.1000000000000000055511151231257827021181583404541015625, pero print(0.1) muestra 0.1. ¿Por qué?

    Elige una respuesta.

    Ver la respuesta: pregunta 2 de 2

    Respuesta: print() muestra el decimal más corto que se guarda como el mismo float

    El valor exacto de un float suele tener muchas cifras. print() y repr() eligen el decimal más corto que se guardaría como el mismo float, lo que oculta el error de un literal suelto hasta que un cálculo produce un float que necesita más cifras.

El rango de un float es enorme, pero su precisión no

Lo grande y lo preciso que es Python · float_limits.py
import sys

print(sys.float_info.max)  # the largest float
print(sys.float_info.max * 10)  # past it: infinity, and no error
try:
    sys.float_info.max ** 2  # ** checks for overflow
except OverflowError:
    print("** raised OverflowError")
print(sys.float_info.epsilon)  # the gap between 1.0 and the next float up
print(2.0 ** 53 + 1 == 2.0 ** 53)  # above 2 ** 53 not every whole number fits
print(float(2 ** 53 + 1))

Salida

1.7976931348623157e+308
inf
** raised OverflowError
2.220446049250313e-16
True
9007199254740992.0

Salida registrada con Python 3.14.8 en macOS 26 arm64. Para ejecutarlo tú: mise exec python@3.14.8 -- python3 float_limits.py

  • El float más grande es de unos 1.8 × 10³⁰⁸. Más allá, una multiplicación da inf (infinito) sin ningún error, mientras que ** lanza OverflowError (las líneas try y except lo capturan, como en la lección de los enteros): Python solo comprueba el desbordamiento en algunas operaciones con floats.
  • sys.float_info.epsilon, el épsilon de máquina: La distancia entre 1.0 y el siguiente float hacia arriba, unos 2.2 × 10⁻¹⁶ para un float de Python (sys.float_info.epsilon). Es la razón por la que los floats guardan unas 16 cifras significativas., unos 2.2 × 10⁻¹⁶, es la distancia entre 1.0 y el siguiente float. Cada operación puede desviarse más o menos la mitad de eso en relación con su resultado, y por eso los floats sirven para unas 16 cifras significativas.
  • Los números enteros solo son exactos hasta 2⁵³ (9,007,199,254,740,992). Por encima, las distancias entre floats son mayores que 1, así que float(2 ** 53 + 1) vuelve como 2⁵³. Los int de Python no tienen ese límite, así que guarda los recuentos y el dinero en int cuando puedas.

Pulsa Editar, cambia los dos + 1 de las dos últimas líneas por + 2 y vuelve a ejecutar el programa. 2⁵³ + 2 es en sí un float, el siguiente hacia arriba, así que la comparación imprime False y la última línea imprime 9007199254740994.0.

Punto de control

Comprueba: el rango y la precisión de un float

  1. Pregunta 1 de 2 float(2 ** 53 + 1) da 9007199254740992.0, que es 2 ** 53. ¿Por qué?

    Elige una respuesta.

    Ver la respuesta: pregunta 1 de 2

    Respuesta: Por encima de 2 53 los floats están a 2 de distancia, así que 2 53 + 1 se redondea a un vecino

    Los números enteros solo son exactos en un float hasta 2 ** 53, 9,007,199,254,740,992. Por encima, la distancia entre floats vecinos es 2, así que cada número entero impar se redondea. Guarda los recuentos y los identificadores grandes en int.

  2. Pregunta 2 de 2 ¿Qué da sys.float_info.max * 10?

    Elige una respuesta.

    Ver la respuesta: pregunta 2 de 2

    Respuesta: inf

    Más allá del float más grande, de unos 1.8 × 10³⁰⁸, una multiplicación da inf sin ningún error, mientras que ** lanza OverflowError: Python solo comprueba el desbordamiento en algunas operaciones con floats.

Los floats calculados necesitan una tolerancia, así que usa math.isclose()

Como un float calculado suele llevar un error de redondeo diminuto, == es la prueba equivocada para él. Pregunta en su lugar si dos valores están lo bastante cerca:

Comparar con una tolerancia Python · compare_floats.py
import math

total = 0.1 + 0.2
print(total == 0.3)
print(math.isclose(total, 0.3))  # within a relative tolerance of 1e-09

balance = 100.0 - 99.9 - 0.1  # should be zero
print(balance)
print(math.isclose(balance, 0.0))  # relative tolerance alone never accepts 0
print(math.isclose(balance, 0.0, abs_tol=1e-9))  # add an absolute tolerance

Salida

False
True
-5.689893001203927e-15
False
True

Salida registrada con Python 3.14.8 en macOS 26 arm64. Para ejecutarlo tú: mise exec python@3.14.8 -- python3 compare_floats.py

math.isclose(a, b) acepta los dos valores cuando su diferencia es como mucho rel_tol veces el mayor de los dos en magnitud, una tolerancia relativa: La mayor diferencia permitida entre dos valores, como proporción del mayor. math.isclose() usa rel_tol=1e-09 por defecto, unas nueve cifras coincidentes.; el rel_tol=1e-09 por defecto significa unas nueve cifras coincidentes, sea cual sea el tamaño de los números. Cerca de cero esa regla falla: ningún número salvo el 0 está cerca de 0 en relación con su propio tamaño, así que el balance, que debería ser cero pero es -5.7 × 10⁻¹⁵, se rechaza. Añade una tolerancia absoluta: Una diferencia máxima fija permitida entre dos valores, sea cual sea su tamaño. math.isclose() necesita una, abs_tol, cuando un valor puede ser cero o estar cerca., abs_tol, siempre que un valor pueda ser cero o casi, y elígela según el problema: para una cantidad en rupias o en dólares, como este saldo, 1e-9 es una diezmillonésima de paisa o de centavo, muy por debajo de nada que pueda contener una cuenta.

math.isclose() sigue las reglas de IEEE 754 para los valores especiales: el infinito solo está cerca de sí mismo, y NaN: Not a Number (no es un número), el resultado float de una operación sin respuesta razonable, como infinito menos infinito. Toda comparación con él es False, incluso nan == nan; detéctalo con math.isnan(). (abajo) no está cerca de nada, ni siquiera de otro NaN.

Idea clave

Prueba un float calculado con math.isclose(), nunca con ==, y dale un abs_tol siempre que el valor con el que comparas pueda ser cero o estar cerca.

Punto de control

Comprueba: comparar con una tolerancia

  1. Pregunta 1 de 2 ¿Qué imprime esto?

    Lee el código y elige una respuesta.

    import math
    print(math.isclose(0.1 + 0.2, 0.3))
    Ver la respuesta: pregunta 1 de 2

    Respuesta: True

    Con su tolerancia relativa por defecto, isclose() acepta valores cuya diferencia es como mucho una milmillonésima del mayor. 0.1 + 0.2 y 0.3 se diferencian en unos 5.6 × 10⁻¹⁷, así que cuentan como cercanos.

  2. Pregunta 2 de 2 Un saldo calculado debería ser cero pero es -5.7e-15. ¿Qué prueba lo acepta como cero?

    Elige una respuesta.

    Ver la respuesta: pregunta 2 de 2

    Respuesta: math.isclose(balance, 0.0, abs_tol=1e-9)

    Junto a cero solo funciona una tolerancia absoluta: isclose(x, 0) solo con rel_tol significa abs(x) <= rel_tol * abs(x), que es False para cualquier x salvo 0. Elige abs_tol según el problema; para el dinero, 1e-9 está muy por debajo de un paisa.

Los errores de redondeo se acumulan cuando sumas muchos floats

Cada suma redondea su resultado, y los pequeños errores se pueden acumular. Recorre diez sumas de 0.1 y mira cómo total se aleja de los valores decimales y vuelve:

Interactivo · línea a línea Diez sumas de 0.1, cada una redondeada Recorre el bucle y mira total. Cada pasada suma 0.1 y redondea el resultado a un float, y los pequeños errores van y vienen antes de que el bucle termine un poco por debajo de 1.0.

Programa · adding_up.py

import math

total = 0.0
for _ in range(10):
    total += 0.1  # ten additions, each one rounded
print(total)

print(sum([0.1] * 10))  # sum() keeps track of the rounding errors
print(math.fsum([0.1] * 10))

values = [1e16, 1e-16, 1.0]
print(sum(values), math.fsum(values))  # here only fsum() gets it right

Variables

Después de la línea 12: total vale 0.9999999999999999; _ vale 9; values vale [1e+16, 1e-16, 1.0].total0.9999999999999999_9values1e+1601e-1611.02
  • recién tomado por el bucle
  • cambiado en este paso
  • ya recorrido por el bucle
  • se lee a continuación
  • donde se detuvo el bucle
  • el valor stop, que nunca se da

Impreso hasta ahora

0.9999999999999999
1.0
1.0
1e+16 1.0000000000000002e+16

Cada paso se registró de una ejecución con Python 3.14.8 en macOS 26 arm64.

El dibujo muestra las variables cuando termina el programa, y los 29 pasos del programa aparecen abajo.

Línea ejecutada 12
Línea siguiente fin
Vuelta del bucle –
Todos los pasos en texto
  1. Inicio. Todavía no se ha ejecutado ninguna línea, así que no hay variables. Python empieza por la línea 1.
  2. Línea 1. import math carga math.
  3. Línea 3. total = 0.0 asigna 0.0 a total.
  4. Línea 4. for _ in range(10): da su primer número: _ es 0.
  5. Línea 5. total += 0.1 cambia total de 0.0 a 0.1.
  6. Línea 4. for _ in range(10): da el número siguiente: _ es 1.
  7. Línea 5. total += 0.1 cambia total de 0.1 a 0.2.
  8. Línea 4. for _ in range(10): da el número siguiente: _ es 2.
  9. Línea 5. total += 0.1 cambia total de 0.2 a 0.30000000000000004. Lo clave La tercera suma cae en el float justo por encima del más cercano a 0.3, el 0.30000000000000004 de la primera línea de la lección.
  10. Línea 4. for _ in range(10): da el número siguiente: _ es 3.
  11. Línea 5. total += 0.1 cambia total de 0.30000000000000004 a 0.4. El redondeo puede anular un error igual que crearlo. Esta suma cae en el float más cercano a 0.4, que se imprime como 0.4.
  12. Línea 4. for _ in range(10): da el número siguiente: _ es 4.
  13. Línea 5. total += 0.1 cambia total de 0.4 a 0.5.
  14. Línea 4. for _ in range(10): da el número siguiente: _ es 5.
  15. Línea 5. total += 0.1 cambia total de 0.5 a 0.6.
  16. Línea 4. for _ in range(10): da el número siguiente: _ es 6.
  17. Línea 5. total += 0.1 cambia total de 0.6 a 0.7.
  18. Línea 4. for _ in range(10): da el número siguiente: _ es 7.
  19. Línea 5. total += 0.1 cambia total de 0.7 a 0.7999999999999999. De aquí en adelante el total está un float por debajo del más cercano a cada valor decimal, y las dos sumas siguientes lo mantienen ahí.
  20. Línea 4. for _ in range(10): da el número siguiente: _ es 8.
  21. Línea 5. total += 0.1 cambia total de 0.7999999999999999 a 0.8999999999999999.
  22. Línea 4. for _ in range(10): da el número siguiente: _ es 9.
  23. Línea 5. total += 0.1 cambia total de 0.8999999999999999 a 0.9999999999999999.
  24. Línea 4. A for _ in range(10): no le quedan números: un range se detiene antes de su valor stop, 10, así que el bucle termina.
  25. Línea 6. print(total) imprime 0.9999999999999999. Diez sumas hicieron diez redondeos, y el total termina un float por debajo de 1.0.
  26. Línea 8. print(sum([0.1] * 10)) imprime 1.0. sum() suma los mismos diez valores pero lleva la cuenta de los errores de redondeo sobre la marcha, así que termina en 1.0.
  27. Línea 9. print(math.fsum([0.1] * 10)) imprime 1.0.
  28. Línea 11. values = [1e16, 1e-16, 1.0] hace de values una lista de 3 elementos.
  29. Línea 12. print(sum(values), math.fsum(values)) imprime 1e+16 1.0000000000000002e+16. Era la última línea, así que el programa termina.

El bucle redondea después de cada paso y termina un poco por debajo de 1.0. sum() lleva la cuenta de los errores de redondeo sobre la marcha (un algoritmo llamado suma de Neumaier) y obtiene exactamente 1.0. math.fsum() va más allá y sigue varias sumas parciales, así que no se pierde precisión por el camino. La última línea muestra un caso en el que solo fsum() acierta: el total real es un poco más de 10000000000000001, y el float más cercano a eso es 1.0000000000000002e+16.

Nota de versión

El sum() más preciso de los floats es nuevo en Python 3.12. Python 3.11 y anteriores suman los floats uno a uno, así que allí sum([0.1] * 10) da 0.9999999999999999, lo mismo que el bucle.

Punto de control

Comprueba: sumar muchos floats

  1. Pregunta 1 de 2 ¿Qué imprime esto?

    Lee el código y elige una respuesta.

    total = 0.0
    for _ in range(10):
        total += 0.1
    print(total == 1.0)
    Ver la respuesta: pregunta 1 de 2

    Respuesta: False

    Cada += redondea su resultado, y después de diez el total es 0.9999999999999999, un float por debajo de 1.0, así que == da False. math.isclose(total, 1.0) daría True.

  2. Pregunta 2 de 2 Un programa suma 100.000 longitudes medidas, como floats, y necesita el total más preciso que pueda dar un float. ¿Qué debería usar?

    Elige una respuesta.

    Ver la respuesta: pregunta 2 de 2

    Respuesta: math.fsum(lengths)

    math.fsum() da el total float más preciso, sum() se acerca desde Python 3.12, y un bucle de sumas sin más es el menos preciso.

round() redondea el valor guardado, no el que escribiste

round(), el formato e int() Python · rounding_surprises.py
from decimal import Decimal

print(round(2.675, 2))  # 2.67, not 2.68
print(Decimal(2.675))  # the value really stored is a little below 2.675
print(f"{2.675:.2f}")  # formatting rounds the stored value too
print(round(0.125, 2))  # 0.125 is exact: a true tie, so half to even

percent = 0.57 * 100
print(percent)
print(int(percent))  # int() drops the fraction: 56
print(round(percent))  # round first: 57

Salida

2.67
2.67499999999999982236431605997495353221893310546875
2.67
0.12
56.99999999999999
56
57

Salida registrada con Python 3.14.8 en macOS 26 arm64. Para ejecutarlo tú: mise exec python@3.14.8 -- python3 rounding_surprises.py

round(2.675, 2) da 2.67, no 2.68, porque el float escrito como 2.675 en realidad está un poco por debajo, así que no hay empate que redondear hacia arriba. Formatear con :.2f redondea el mismo valor guardado y coincide. 0.125, en cambio, es exactamente ⅛, un empate de verdad, y round() lo manda al vecino par, 0.12.

Un error común: int() después de una aritmética con floats

0.57 * 100 es 56.99999999999999, y int() quita la fracción, así que el resultado es 56 en lugar de 57. Los porcentajes, los precios en paise o en centavos y otros pasos de “convertir a un número entero” fallan así. Usa round() en su lugar, que también devuelve un int.

Calculadora de redondeo (en inglés) Redondea con aritmética decimal exacta y todos los modos de redondeo uno al lado del otro.

Punto de control

Comprueba: redondear el valor guardado

  1. Pregunta 1 de 2 ¿Qué imprime esto?

    Lee el código y elige una respuesta.

    print(round(2.675, 2))
    Ver la respuesta: pregunta 1 de 2

    Respuesta: 2.67

    Decimal(2.675) muestra el valor guardado, 2.67499999999999982236431605997495353221893310546875. Está por debajo del punto medio entre 2.67 y 2.68, así que round() da 2.67.

  2. Pregunta 2 de 2 percent = 0.57 * 100. ¿Qué expresión da el número entero 57?

    Elige una respuesta.

    Ver la respuesta: pregunta 2 de 2

    Respuesta: round(percent)

    0.57 * 100 es 56.99999999999999, un poco por debajo de 57. Todo lo que redondea hacia abajo o quita la fracción pierde una unidad; round() va al número entero más cercano.

El infinito, NaN y el cero negativo siguen sus propias reglas

Los valores float especiales Python · special_values.py
import math

inf = float("inf")
nan = float("nan")  # "not a number"
print(inf > 10 ** 300, -inf < 0)
print(inf - inf, inf * 0)  # no sensible answer: nan
print(nan == nan, nan != nan)  # nan is not equal even to itself
print(math.isnan(nan), math.isinf(inf), math.isfinite(1e308))
print(0.0 == -0.0, math.copysign(1, -0.0))  # equal, but the sign is kept

Salida

True True
nan nan
False True
True True True
True -1.0

Salida registrada con Python 3.14.8 en macOS 26 arm64. Para ejecutarlo tú: mise exec python@3.14.8 -- python3 special_values.py

  • float("inf") y -float("inf") son mayor y menor que cualquier número finito.
  • nan (“not a number”, no es un número) es el resultado de las operaciones sin respuesta razonable, como infinito menos infinito. Toda comparación con él es False, incluso nan == nan; solo != es True. Detéctalo con math.isnan(), y el infinito con math.isinf(), o “un número normal” con math.isfinite().
  • -0.0 es igual a 0.0, pero conserva su signo, que math.copysign() puede leer.

Un NaN en tus datos es fácil de pasar por alto, porque las comparaciones con él fallan en silencio. max() se queda con el primer elemento y solo lo sustituye por uno que compare como mayor, así que un NaN al principio gana y un NaN más adelante se ignora. Y dividir un float entre cero no da inf en Python; lanza ZeroDivisionError:

Un NaN entre las lecturas Python · nan_in_data.py
nan = float("nan")
print(max([nan, 3.0, 1.0]))  # nan: no reading compares greater than nan
print(max([1.0, 3.0, nan]))  # 3.0: the same readings in another order

try:
    1.0 / 0.0
except ZeroDivisionError as error:  # Python raises instead of giving inf
    print("ZeroDivisionError:", error)

Salida

nan
3.0
ZeroDivisionError: division by zero

Salida registrada con Python 3.14.8 en macOS 26 arm64. Para ejecutarlo tú: mise exec python@3.14.8 -- python3 nan_in_data.py

Comprueba los valores que llegan con math.isnan(), y deja fuera NaN o sustitúyelo antes de calcular un máximo, una ordenación o un total.

Punto de control

Comprueba: infinito, NaN y cero negativo

  1. Pregunta 1 de 2 ¿Qué imprime esto?

    Lee el código y elige una respuesta.

    nan = float("nan")
    print(nan == nan, nan != nan)
    Ver la respuesta: pregunta 1 de 2

    Respuesta: False True

    IEEE 754 hace que nan sea distinto de todo, incluido él mismo. Por eso math.isnan() es la forma de detectarlo.

  2. Pregunta 2 de 2 ¿Qué es float("inf") - float("inf")?

    Elige una respuesta.

    Ver la respuesta: pregunta 2 de 2

    Respuesta: nan

    IEEE 754 da nan en las operaciones sin respuesta razonable, como inf - inf e inf * 0, como imprime special_values.py.

Decimal y Fraction son exactos donde un float no lo es

La biblioteca estándar tiene otros dos tipos de número para los trabajos en los que el redondeo binario no es aceptable. Una lección posterior trata los dos a fondo; esto es cuándo recurrir a cada uno:

Decimal y Fraction Python · exact_types.py
from decimal import Decimal
from fractions import Fraction

print(Decimal("0.1") + Decimal("0.2"))  # decimal arithmetic, from strings
print(Decimal("0.1") + Decimal("0.2") == Decimal("0.3"))
print(Decimal(0.1))  # from a float: the float's error comes along

print(Fraction(1, 3) + Fraction(1, 6))  # exact ratios
print(Fraction(1, 3) * 3 == 1)

print(float.from_number(Fraction(1, 4)))  # new in 3.14: numbers only
try:
    float.from_number("3.5")  # float("3.5") would parse the text
except TypeError as error:
    print("TypeError:", error)

Salida

0.3
True
0.1000000000000000055511151231257827021181583404541015625
1/2
True
0.25
TypeError: must be real number, not str

Salida registrada con Python 3.14.8 en macOS 26 arm64. Para ejecutarlo tú: mise exec python@3.14.8 -- python3 exact_types.py

¿float, Decimal o Fraction?
Criterio floatdecimal.Decimalfractions.Fraction
Guarda una fracción binaria con 53 bits significativoscifras decimales: 28 cifras significativas por defecto, ajustableun numerador y un denominador exactos
Exacto para mitades, cuartos, octavos… y números enteros hasta 2⁵³cantidades decimales como 0.1 y 19.99cualquier cociente de dos enteros, como 1/3
Aritmética el hardware de punto flotante del procesadorsoftwaresoftware, con numeradores y denominadores que pueden crecer mucho
Cuándo elegirlo Medidas, ciencia, gráficos y la mayoría de los cálculos del día a díaDinero, y todo lo que tenga que redondear como la gente redondea los decimalesCocientes exactos, como probabilidades o escalar recetas

Construye un Decimal a partir de una cadena, Decimal("0.1"), o de un int. Decimal(0.1) copia el float exactamente, con error y todo, como muestra la tercera línea de la salida.

Nota de versión

Novedad de Python 3.14: float.from_number() convierte un número (un int, un Fraction, un Decimal…) en un float y lanza TypeError con cualquier otra cosa, incluido el texto. float() sigue analizando cadenas como "3.5", así que from_number() es la opción más estricta cuando un valor ya tiene que ser un número.

Punto de control

Comprueba: Decimal y Fraction

  1. Pregunta 1 de 2 ¿Qué expresión da exactamente Decimal('0.3')?

    Elige una respuesta.

    Ver la respuesta: pregunta 1 de 2

    Respuesta: Decimal("0.1") + Decimal("0.2")

    Decimal hace aritmética decimal, pero solo es tan exacto como aquello de lo que parte. Constrúyelo a partir de cadenas o de int, nunca de floats.

  2. Pregunta 2 de 2 ¿Qué tipo guarda 1/3 exactamente?

    Elige una respuesta.

    Ver la respuesta: pregunta 2 de 2

    Respuesta: fractions.Fraction

    Fraction guarda exactamente cualquier cociente de dos enteros. Decimal es exacto para cantidades decimales como 0.1, y float para fracciones binarias como 0.75.

Practica: compara floats de la forma segura

Dos funciones pequeñas ponen a trabajar las reglas de comparación de esta lección: una decide si dos floats son iguales salvo errores de redondeo, y la otra encuentra los pares en los que == se equivoca. Sus pruebas de ejemplo se ejecutan en tu navegador, y la primera pista está ahí cuando la necesites:

Ejercicio · Fácil · Python

Comparar floats con una tolerancia

Escribe dos funciones en compare.py.

La primera, almost_equal(a, b), devuelve True cuando los floats a y b son iguales salvo errores de redondeo, y False en caso contrario. Usa math.isclose() con su tolerancia relativa por defecto (rel_tol=1e-09, unas nueve cifras coincidentes) y una tolerancia absoluta de ABS_TOL, que el código inicial fija en 1e-12, para que los resultados cerca de cero también cuenten como cercanos.

La segunda, surprises(pairs), recibe una lista de pares (a, b) y devuelve, en su orden original, los pares que == considera distintos pero almost_equal() considera iguales: las comparaciones en las que == se equivocaría.

  • almost_equal(0.1 + 0.2, 0.3) es True
  • almost_equal(1e-15, 0.0) es True
  • almost_equal(1e-9, 0.0) es False
  • almost_equal(float("nan"), float("nan")) es False
  • surprises([(0.1 + 0.2, 0.3), (1.0, 1.0), (2.0, 3.0)]) es [(0.30000000000000004, 0.3)]

Las pruebas de ejemplo comparan doce pares, entre ellos infinitos, NaN, 0.0 y -0.0, y valores muy cerca de cero.

Código inicial · compare.py

import math

ABS_TOL = 1e-12  # how far apart two numbers near zero may be and still count as equal


def almost_equal(a, b):
    """Return True when a and b are equal within rel_tol=1e-09 or abs_tol=ABS_TOL."""
    # Replace this line with your code.
    return a == b


def surprises(pairs):
    """Return the pairs (a, b) that == calls different but almost_equal() calls equal, in order."""
    # Replace this line with your code.
    return []
Las pruebas de ejemplo · test_compare.py
from compare import almost_equal, surprises

nan = float("nan")
inf = float("inf")


def test_rounding_errors():
    """treats numbers as equal when they differ only by a tiny fraction of their size"""
    assert almost_equal(0.1 + 0.2, 0.3) is True
    assert almost_equal(1.1 + 2.2, 3.3) is True
    assert almost_equal(1e20, 1e20 + 1e5) is True


def test_real_differences():
    """keeps numbers that really differ apart"""
    assert almost_equal(1.0, 1.001) is False
    assert almost_equal(100.0, 100.5) is False


def test_relative_tolerance():
    """allows a relative difference of 1e-09, and no more"""
    assert almost_equal(1.0, 1.0 + 5e-10) is True
    assert almost_equal(1.0, 1.0 + 2e-9) is False


def test_near_zero():
    """allows an absolute difference of 1e-12 near zero, and no more"""
    assert almost_equal(1e-15, 0.0) is True
    assert almost_equal(100.0 - 99.9 - 0.1, 0.0) is True
    assert almost_equal(2e-12, 0.0) is False
    assert almost_equal(1e-9, 0.0) is False


def test_signed_zero():
    """treats 0.0 and -0.0 as equal"""
    assert almost_equal(0.0, -0.0) is True


def test_special_values():
    """follows the IEEE 754 rules for infinity and NaN"""
    assert almost_equal(inf, inf) is True
    assert almost_equal(inf, -inf) is False
    assert almost_equal(nan, nan) is False
    assert almost_equal(nan, 1.0) is False


def test_surprises():
    """finds the pairs that == gets wrong, in their original order"""
    pairs = [
        (0.1 + 0.2, 0.3),
        (1.0, 1.0),
        (1e-15, 0.0),
        (1e-9, 0.0),
        (0.0, -0.0),
        (nan, nan),
        (inf, inf),
        (inf, -inf),
        (1e20, 1e20 + 1e5),
        (1.0, 1.001),
        (1.1 + 2.2, 3.3),
        (2.5, 2.5),
    ]
    assert surprises(pairs) == [(0.1 + 0.2, 0.3), (1e-15, 0.0), (1e20, 1e20 + 1e5), (1.1 + 2.2, 3.3)]
Una pista

math.isclose(a, b, abs_tol=ABS_TOL) ya usa rel_tol=1e-09, su valor por defecto. Para surprises(), empieza con una lista vacía, recorre los pares con for a, b in pairs:, y append((a, b)) cuando a != b y almost_equal(a, b) sean verdaderas las dos.

Las pruebas de ejemplo se ejecutan en este dispositivo, en tu navegador (Pyodide): no se envía nada a mysmartcopilot.com. La primera ejecución descarga Python (unos 13.5 MB), que se guarda para las siguientes. Una comprobación en tu navegador es una orientación para ti, no la prueba de que el código sea correcto con cualquier entrada.

Cuando pasen las pruebas, intenta las preguntas de abajo. Empiezan donde tus respuestas son más flojas, suben de nivel a medida que aciertas y explican cada opción en cuanto la eliges:

Práctica que se adapta a ti

Practica esta lección

18 preguntas sobre 7 ideas de esta lección. Cada respuesta se explica al momento, y lo que aciertas se guarda en este navegador.

  1. Pregunta 1 de 18 ¿Por qué 0.1 + 0.2 == 0.3 es False en Python?

    Elige una respuesta.

    Ver la respuesta: pregunta 1 de 18

    Respuesta: 0.1, 0.2 y 0.3 se guardan como las fracciones binarias más cercanas, y la suma cae en un float distinto del que se guarda para 0.3

    Las fracciones con un factor distinto de 2 en el denominador, como 1/10, nunca terminan en binario, así que cada literal se guarda como el float más cercano. La suma exacta de los 0.1 y 0.2 guardados queda a medio camino entre dos floats y se redondea hacia arriba, mientras que 0.3 se guarda como el float de abajo. Los demás lenguajes que usan los mismos floats binarios coinciden.

  2. Pregunta 2 de 18 ¿Cuáles de estos valores se guardan exactos como floats?

    Elige todas las respuestas correctas.

    Ver la respuesta: pregunta 2 de 18

    Respuesta:

    • 0.125
    • 0.5
    • 0.75

    Una fracción es exacta en binario cuando su denominador, en su forma irreducible, es una potencia de 2: ½, ¾ y ⅛ cumplen. 1/10, 1/5 y 1/3 tienen otros factores en el denominador, así que se guardan como el float más cercano.

  3. Pregunta 3 de 18 ¿Qué es sys.float_info.epsilon, unos 2.2e-16?

    Elige una respuesta.

    Ver la respuesta: pregunta 3 de 18

    Respuesta: La distancia entre 1.0 y el siguiente float hacia arriba

    sys.float_info.epsilon es la distancia de 1.0 al siguiente float. Cada operación puede desviarse más o menos la mitad de eso, en relación con su resultado, así que los floats sirven para unas 16 cifras significativas.

  4. Pregunta 4 de 18 ¿Cuál de estos números enteros guarda float() exactamente?

    Elige una respuesta.

    Ver la respuesta: pregunta 4 de 18

    Respuesta: 2 ** 53

    Un float guarda 53 bits significativos, así que cada número entero hasta 2 ** 53, 9,007,199,254,740,992, es exacto. Por encima las distancias crecen, duplicándose en cada potencia de 2, y los números enteros se redondean al float más cercano.

  5. Pregunta 5 de 18 Una API envía identificadores de pedido como 9007199254740993 como números JSON. Un cliente que guarda cada número JSON como un float de 64 bits muestra ese identificador como 9007199254740992. ¿Cuál es la causa, y el arreglo?

    Elige una respuesta.

    Ver la respuesta: pregunta 5 de 18

    Respuesta: El identificador está por encima de 2 ** 53, donde los floats no pueden guardar todos los números enteros; envía los identificadores como cadenas

    9007199254740993 es 2 ** 53 + 1, el primer número entero que un float no puede guardar. Los identificadores, los números de cuenta y otros identificadores son texto, no números: envíalos como cadenas.

  6. Pregunta 6 de 18 ¿Qué significa el rel_tol=1e-09 por defecto de math.isclose()?

    Elige una respuesta.

    Ver la respuesta: pregunta 6 de 18

    Respuesta: La diferencia puede ser como mucho una milmillonésima del mayor de los dos valores

    isclose() acepta a y b cuando abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol). Con los valores por defecto, eso es una diferencia de como mucho una milmillonésima del valor mayor, y nada junto a cero.

  7. Pregunta 7 de 18 ¿Qué imprime esto?

    Lee el código y elige una respuesta.

    import math
    print(math.isclose(1e-10, 0.0))
    Ver la respuesta: pregunta 7 de 18

    Respuesta: False

    Con solo la tolerancia relativa por defecto, un valor está cerca de 0 solo si es 0: la diferencia permitida es rel_tol veces el valor mayor, y eso se reduce a nada junto a cero. Pasa una tolerancia absoluta, por ejemplo abs_tol=1e-9, cuando los valores puedan estar cerca de cero.

  8. Pregunta 8 de 18 ¿Qué imprime esto en Python 3.14?

    Lee el código y elige una respuesta.

    print(sum([0.1] * 10))
    Ver la respuesta: pregunta 8 de 18

    Respuesta: 1.0

    El sum() más preciso de los floats llegó en Python 3.12. El bucle de adding_up.py redondea diez veces e imprime 0.9999999999999999; sum() de los mismos diez valores imprime 1.0.

  9. Pregunta 9 de 18 ¿Qué imprime este programa, el que se recorrió en la lección, en Python 3.14?

    Lee el código y elige una respuesta.

    import math
    
    total = 0.0
    for _ in range(10):
        total += 0.1
    print(total)
    
    print(sum([0.1] * 10))
    print(math.fsum([0.1] * 10))
    
    values = [1e16, 1e-16, 1.0]
    print(sum(values), math.fsum(values))
    Ver la respuesta: pregunta 9 de 18

    Respuesta: 0.9999999999999999 1.0 1.0 1e+16 1.0000000000000002e+16

    Diez sumas redondeadas dan 0.9999999999999999. sum() y fsum() dan 1.0. Para [1e16, 1e-16, 1.0] el total real es un poco más de 10000000000000001, y solo fsum() encuentra el float más cercano a él, 1.0000000000000002e+16.

  10. Pregunta 10 de 18 ¿Por qué round(2.675, 2) da 2.67?

    Elige una respuesta.

    Ver la respuesta: pregunta 10 de 18

    Respuesta: El float escrito como 2.675 se guarda un poco por debajo de 2.675, así que no hay empate, y redondea hacia abajo

    round() redondea el valor que se guarda, y el float de 2.675 está un poco por debajo de 2.675. Usa Decimal("2.675") cuando necesites redondear el valor decimal que escribiste.

  11. Pregunta 11 de 18 ¿Qué imprime rounding_surprises.py?

    ¿Qué imprime este programa? Elige una respuesta.

    from decimal import Decimal
    
    print(round(2.675, 2))  # 2.67, not 2.68
    print(Decimal(2.675))  # the value really stored is a little below 2.675
    print(f"{2.675:.2f}")  # formatting rounds the stored value too
    print(round(0.125, 2))  # 0.125 is exact: a true tie, so half to even
    
    percent = 0.57 * 100
    print(percent)
    print(int(percent))  # int() drops the fraction: 56
    print(round(percent))  # round first: 57
    Ver la respuesta: pregunta 11 de 18

    Respuesta: imprime

    2.67
    2.67499999999999982236431605997495353221893310546875
    2.67
    0.12
    56.99999999999999
    56
    57

    El float escrito como 2.675 está un poco por debajo de 2.675, así que tanto round() como :.2f dan 2.67. 0.125 es exacto, un empate de verdad, y va al vecino par, 0.12. 0.57 * 100 está un poco por debajo de 57, así que int() da 56 y round() da 57.

  12. Pregunta 12 de 18 Una aplicación de una tienda lee un precio en rupias como el float 19.99 y lo convierte en paise con int(price * 100). El resultado es 1998, un paisa de menos. ¿Qué cambio lo arregla?

    Elige una respuesta.

    Ver la respuesta: pregunta 12 de 18

    Respuesta: round(price * 100)

    Convertir un resultado float en un número entero tiene que redondear, no truncar. Mejor aún, lee el precio de su texto con Decimal, o guarda las cantidades en paise como int desde el principio.

  13. Pregunta 13 de 18 ¿Qué prueba es True exactamente cuando x es NaN?

    Elige una respuesta.

    Ver la respuesta: pregunta 13 de 18

    Respuesta: math.isnan(x)

    NaN no es igual ni siquiera a sí mismo, así que == nunca puede encontrarlo. math.isnan() es la prueba; math.isinf() encuentra los infinitos, y math.isfinite() los números normales.

  14. Pregunta 14 de 18 ¿Qué imprime esto?

    Lee el código y elige una respuesta.

    import math
    print(0.0 == -0.0, math.copysign(1, -0.0))
    Ver la respuesta: pregunta 14 de 18

    Respuesta: True -1.0

    IEEE 754 tiene dos ceros. Comparan como iguales, pero -0.0 recuerda su signo, y math.copysign(1, -0.0) es -1.0.

  15. Pregunta 15 de 18 ¿Qué imprime esto?

    Lee el código y elige una respuesta.

    readings = [float("nan"), 3.0, 1.0]
    print(max(readings))
    Ver la respuesta: pregunta 15 de 18

    Respuesta: nan

    Con un NaN en los datos, max() y sorted() dan respuestas que dependen del orden de los elementos. Deja fuera NaN o sustitúyelo antes de calcular, después de comprobarlo con math.isnan().

  16. Pregunta 16 de 18 ¿Qué imprime esto?

    Lee el código y elige una respuesta.

    from decimal import Decimal
    print(Decimal("0.1") + Decimal("0.2"))
    Ver la respuesta: pregunta 16 de 18

    Respuesta: 0.3

    Construidos a partir de cadenas, Decimal("0.1") y Decimal("0.2") son exactos, y su suma también, que se imprime como 0.3.

  17. Pregunta 17 de 18 El programa de una tienda suma precios como 19.99 y tiene que cuadrar con el tique hasta el último paisa o centavo. ¿Qué opción encaja?

    Elige una respuesta.

    Ver la respuesta: pregunta 17 de 18

    Respuesta: Decimal valores construidos a partir de cadenas, como Decimal("19.99")

    Decimal hace aritmética decimal, así que 19.99 es exacto cuando viene de la cadena "19.99". Construido a partir de un float, un Decimal o un Fraction copia exactamente el error binario del float. Redondear los floats después de cada paso sigue partiendo de valores inexactos. (Contar en paise o centavos enteros con int también funciona.)

  18. Pregunta 18 de 18 Una función tiene que convertir cualquier número, un int, un Fraction o un Decimal, en un float, y tiene que rechazar texto como "3.5". ¿Qué llamada lo hace en Python 3.14?

    Elige una respuesta.

    Ver la respuesta: pregunta 18 de 18

    Respuesta: float.from_number(x)

    float() analiza texto sin problema, lo que está mal para una función que solo debe aceptar números. float.from_number() es la conversión estricta, y exact_types.py muestra el TypeError que lanza con "3.5".

Preguntas de entrevista

Júnior · ¿Por qué 0.1 + 0.2 no es igual a 0.3 en Python?

Porque ninguno de los tres se puede guardar exacto. Un float es un doble IEEE 754, una fracción binaria con 53 bits significativos, y el binario solo guarda exacta una fracción si su denominador es una potencia de 2. El denominador de 1/10 no lo es, así que el literal 0.1 se guarda como el float más cercano, un poco por encima de 0.1, y 0.2 un poco por encima de 0.2. Su suma exacta queda a medio camino entre dos floats vecinos y se redondea al par, el float que se imprime como 0.30000000000000004, mientras que el literal 0.3 se guarda como el float justo por debajo. Dos floats distintos no son iguales. No hay nada roto, y todos los lenguajes que usan estos floats obtienen la misma respuesta. Compara los floats calculados con math.isclose(), y usa decimal.Decimal, construido a partir de cadenas, cuando cantidades decimales como el dinero tengan que ser exactas.

Para recordar

  • Los floats son fracciones binarias con 53 bits significativos; la mayoría de las fracciones decimales, 0.1 incluida, se guardan como el valor de ese tipo más cercano, así que los pequeños errores son normales.
  • Nunca compares floats calculados con ==. Usa math.isclose(), con un abs_tol siempre que los valores puedan estar cerca de cero.
  • sum() suma floats con precisión desde Python 3.12; math.fsum() es el más preciso.
  • round(2.675, 2) es 2.67 por el valor guardado; usa round(), no int(), cuando conviertas un resultado float en un número entero.
  • NaN no es igual a sí mismo: detéctalo con math.isnan().
  • Usa Decimal, construido a partir de cadenas, para el dinero, y Fraction para los cocientes exactos; deja los floats para las medidas y la ciencia.

Términos de esta lección

tolerancia absoluta
Una diferencia máxima fija permitida entre dos valores, sea cual sea su tamaño. math.isclose() necesita una, abs_tol, cuando un valor puede ser cero o estar cerca.
IEEE 754
El estándar de aritmética de punto flotante que siguen casi todas las computadoras. Un float de Python es su doble de 64 bits, una fracción binaria con 53 bits significativos y un exponente.
épsilon de máquina
La distancia entre 1.0 y el siguiente float hacia arriba, unos 2.2 × 10⁻¹⁶ para un float de Python (sys.float_info.epsilon). Es la razón por la que los floats guardan unas 16 cifras significativas.
NaN
Not a Number (no es un número), el resultado float de una operación sin respuesta razonable, como infinito menos infinito. Toda comparación con él es False, incluso nan == nan; detéctalo con math.isnan().
tolerancia relativa
La mayor diferencia permitida entre dos valores, como proporción del mayor. math.isclose() usa rel_tol=1e-09 por defecto, unas nueve cifras coincidentes.

Referencias

Herramientas relacionadas

Informar de un problema con esta lección (en inglés)

Respuestas rápidas y búsqueda de herramientas

Escribe para buscar herramientas o para obtener una respuesta rápida (en inglés), por ejemplo 18% of 2500. Usa las flechas arriba y abajo para recorrer los resultados, Intro para elegir y Escape para cerrar.