Calcular cantidades decimales con precisión

Ciencia y tecnologíaCalcular cantidades decimales con precisión

El inventario contará unidades enteras pero muchos programas necesitan trabajar con valores decimales. En esta práctica aprenderás por qué una cifra que se ve sencilla puede no tener una representación binaria exacta. Utilizarás Decimal para cálculos decimales controlados y separarás el valor de la forma en que lo presentas.

Entender el límite de float

Los números float representan valores mediante una cantidad finita de bits. Algunas fracciones decimales, como una décima, no tienen una representación binaria finita. Por eso una operación puede producir una aproximación muy cercana al resultado esperado sin ser exactamente igual. No significa que Python sume al azar ni que todos los float sean inadecuados.

Los float resultan útiles en numerosos cálculos científicos y mediciones donde ya existe tolerancia. Cuando una regla exige una aritmética decimal determinada conviene escoger otra representación. En esta lección usaremos importes inventados para observar el mecanismo. No estamos construyendo un sistema de facturación ni definiendo reglas fiscales.

precio = Decimal("2.35") unidades = 3 subtotal = precio * unidades resultado = subtotal.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP) print(resultado) «`

La salida es 7.05. Construimos Decimal a partir de texto para expresar exactamente los dígitos deseados. Si escribes Decimal(0.1) primero se crea un float y después se convierte su aproximación. Esa conversión no recupera por arte de magia el decimal que imaginabas. Utiliza cadenas cuando el origen es una escritura decimal.

Decidir cuándo redondear

Redondear cada línea y sumar no siempre produce lo mismo que sumar todas las líneas y redondear al final. Ambas operaciones pueden seguir reglas distintas. Antes de programar un cálculo define en qué momento se reduce la precisión y con qué criterio. No dejes esa decisión escondida en una función de presentación.

En el ejemplo hemos elegido ROUND_HALF_UP para mostrar una regla concreta: en un empate se redondea alejándose de cero. No es una norma universal para cualquier actividad. Decimal ofrece otros modos. Python también tiene convenciones propias en round. El curso te enseña a declarar la elección y comprobarla, no a dar por válida una política para todos los documentos.

Prueba con Decimal("1.005") y una precisión de centésimas. Después compara el redondeo de dos cantidades iguales por separado con el redondeo de su suma. La diferencia potencial no es un fallo del programa: revela que has definido operaciones diferentes. Tus pruebas deben representar la que necesita la aplicación.

Convertir entradas de forma previsible

Una persona en España puede escribir una coma decimal. Puedes decidir admitirla si no admites separadores de miles en ese mismo campo. La transformación debe estar documentada. Un texto como «1,234» es ambiguo si a veces representa mil doscientos treinta y cuatro y otras una cantidad con tres decimales. No intentes interpretar ambos usos sin contexto.

Para esta práctica aceptaremos un punto o una coma decimal pero ningún separador de miles. Quitaremos espacios exteriores. Rechazaremos valores especiales no finitos como NaN e Infinity porque no representan un importe ordinario. Decimal puede construirlos y por eso convertir correctamente no basta para validar el dominio.

def leer_importe(texto): limpio = texto.strip().replace(",", ".") try: valor = Decimal(limpio) except InvalidOperation as error: raise ValueError("Importe no válido") from error if not valor.is_finite() or valor < 0: raise ValueError("Usa un importe finito no negativo") return valor «`

Esta función convierte y rechaza ciertos valores pero no impone dos decimales de entrada. Esa sería otra regla que tendrías que añadir si tu aplicación la necesita. Por ahora conservará la precisión recibida y el cálculo decidirá cuándo redondear. Separar ambas decisiones evita perder información demasiado pronto.

Mostrar dos decimales sin confundir operaciones

El formato de salida permite presentar un número con dos cifras decimales. Eso no modifica necesariamente la variable original. Si necesitas utilizar un valor ya redondeado en otro cálculo obtén explícitamente ese valor con quantize. Si solo quieres una apariencia uniforme aplica el formato al mostrarlo. Explica cuál de las dos cosas estás haciendo.

Tampoco mezcles Decimal con float en las operaciones. Mantén los valores decimales en la misma representación y utiliza enteros para cantidades de unidades. Si recibes datos de un archivo conserva los textos originales hasta validarlos. Ese recorrido permite decidir con claridad dónde se transforma cada campo y qué errores pueden aparecer.

Errores habituales

Una comparación exacta entre resultados float puede fallar por pequeñas aproximaciones. Para mediciones podría corresponder una comparación con tolerancia pero no uses una tolerancia improvisada para ocultar un problema de redondeo. Elige la representación según el significado del dato y define después la comprobación adecuada.

Otro error consiste en introducir precios en el inventario final solo porque acabas de aprender Decimal. Cada campo nuevo añade reglas, pruebas y decisiones de almacenamiento. Esta práctica es independiente a propósito. Cuando amplíes el proyecto podrás incorporar precios con una política completa y documentada en lugar de añadir una columna sin pensar qué representa.

Una comprobación adicional

Conserva siempre un caso de empate en tus pruebas de redondeo. Los ejemplos alejados de una frontera pueden dar el mismo resultado con varias políticas diferentes y no revelar una configuración incorrecta. Una entrada como 1.005 permite observar una decisión que no aparece al trabajar únicamente con precios de dos decimales.

Lo que deberías recordar

  • Construye Decimal desde texto.
  • La conversión no sustituye a la validación.
  • Declara cuándo y cómo redondeas.
  • No amplíes el proyecto sin definir nuevas reglas.

Ejercicio práctico

Calcula tres unidades a 2,35 usando leer_importe y Decimal. Anota el resultado antes y después de presentar dos decimales. Repite construyendo un Decimal desde el texto «0.1» y desde el float 0.1. Compara las representaciones y explica de dónde procede la diferencia.

Prueba «12,50», «12.50», «-1», «NaN» y «1.234,56». Las dos primeras se aceptan. Las otras deben rechazarse en las reglas de esta práctica. El último caso contiene un separador de miles que hemos decidido no admitir.

Compara redondear dos valores 1.005 por separado con sumar primero y redondear después. Escribe ambas salidas y formula una regla explícita para una aplicación imaginaria. La práctica estará terminada cuando puedas explicar qué dato aceptas, cuándo redondeas y cómo lo muestras sin confundir esos tres pasos.

Siguiente: Controlar rutas y archivos con pathlib.

Volver al índice de Programar con Python.

Últimos posts

DEJA UNA RESPUESTA

Por favor ingrese su comentario!
Por favor ingrese su nombre aquí

 

Artículos más vistos

Horóscopo diario
Menú diario