Tecnología · GUÍA PRÁCTICA
¿Decimal.quantize lanza InvalidOperation? Revise los dígitos del resultado antes de cambiar la precisión
La precisión de Decimal limita todo el coeficiente, no los decimales. Separe acarreo, ceros añadidos y valores no finitos con una prueba aislada.

InvalidOperation en quantize puede reflejar la capacidad necesaria para el resultado, no los decimales de la entrada. Conserve operandos y contexto antes de aumentar precisión o desactivar la trampa.
1. Registre la operación, no solo la excepción
Guarde traceback, ambos operandos Decimal y sus orígenes. En la llamada que falla registre repr(value), value.as_tuple(), repr(quantum), getcontext().prec, rounding, Emin, Emax, traps y flags existentes. Compruebe si una biblioteca pasa otro context explícitamente. DefaultContext observado en otra parte puede no ser el contexto utilizado.
Separe construcción y cuantización. Un Decimal creado desde float conserva el valor de ese flotante; no recupera el texto decimal original. Si el contrato exige texto, utilice el original. Texto inválido, magnitud no admitida y un fallo posterior de quantize son ramas distintas: no aplique una sola precisión a todas.
2. Cuente después del acarreo y los ceros
La precisión limita todo el coeficiente, no los decimales. En CPython 3.12.14 con ROUND_HALF_EVEN, Decimal('9.995').quantize(Decimal('0.01')) falló con precisión 3 y devolvió 10.00 con precisión 4. El resultado necesita cuatro dígitos: reservar un entero y dos decimales omite el acarreo.
Decimal('1.23').quantize(Decimal('0.0001')) falló con precisión 3 y devolvió 1.2300 con precisión 5. Aunque no cambia el valor, los ceros obligatorios consumen capacidad. Determine la precisión según magnitud admitida, exponente requerido y posible acarreo; revise también los límites de exponente. Ninguna precisión sirve como reparación universal.
3. Mantenga visibles los valores inválidos y aísle el cambio
Antes de aplicar una política de datos finitos, compruebe value.is_finite() y quantum.is_finite(). En las pruebas, NaN silencioso se propagó sin excepción; sNaN e Infinity con quantum finito produjeron InvalidOperation. Capturar excepciones no basta para impedir resultados no finitos.
Al desactivar la trampa InvalidOperation, el caso 9.995 con precisión 3 devolvió NaN y activó esa señal: 10.00 seguía sin caber. Use with localcontext() as ctx y ajuste solo precisión, redondeo y trampas revisados. Preserve el contexto exterior. Si la biblioteca lo sustituye internamente, investigue su comportamiento documentado en vez de cambiar una y otra vez el valor global.
4. Exija un valor, exponente y señales aceptables
Borre flags en el contexto aislado justo antes de la operación y léalos después. Un contrato finito exige result.is_finite(), el valor esperado y result.as_tuple().exponent igual al exponente de quantum. Decida si admite Inexact y Rounded. El caso 10.00 activó ambas señales; los ceros de 1.2300 no activaron ninguna. Sin excepción no equivale a aritmética exacta.
Vuelva a probar entradas normales, acarreo entre enteros, ceros obligatorios, negativos, cero, máxima magnitud admitida y valores especiales rechazados según las reglas reales. Los ocho casos sintéticos verificaron estas ramas y la restauración de precisión exterior, no datos de producción, reglas financieras ni bibliotecas ajenas. Si falla, conserve operandos, contexto y señales y diagnostique esa rama sin ocultar la excepción.
