Python Basics: Controlling Decimal Arithmetic and Rounding
Binary floating-point values cannot represent every decimal fraction exactly. Python’s standard-library decimal module lets you work from decimal strings and choose precision and rounding explicitly.
Use Python 3.12 or newer on Linux. These independent examples calculate sample measurements in memory.
Start with decimal strings
Save as demo_decimal_1.py:
from decimal import Decimal
print("float:", 0.1 + 0.2)
print("Decimal:", Decimal("0.1") + Decimal("0.2"))
print("Float input matches string:", Decimal(0.1) == Decimal("0.1"))Run it from the directory where you saved it:
python3 demo_decimal_1.pyOutput:
float: 0.30000000000000004
Decimal: 0.3
Float input matches string: FalseDecimal(0.1) preserves the already-approximated float value. Use the original string when decimal input matters. Avoid mixing Decimal and float in arithmetic.
Round to two decimal places
Save as demo_decimal_2.py:
from decimal import Decimal, ROUND_HALF_EVEN, ROUND_HALF_UP
step = Decimal("0.01")
for raw in ("1.245", "1.255", "-1.245"):
value = Decimal(raw)
even = value.quantize(step, rounding=ROUND_HALF_EVEN)
up = value.quantize(step, rounding=ROUND_HALF_UP)
print(f"{raw}: half-even={even}, half-up={up}")Run it from the directory where you saved it:
python3 demo_decimal_2.pyOutput:
1.245: half-even=1.24, half-up=1.25
1.255: half-even=1.26, half-up=1.26
-1.245: half-even=-1.24, half-up=-1.25Both choose the nearest value. Ties go to an even final digit with half-even, or away from zero with half-up. quantize() matches the second operand’s exponent; it does not round to arbitrary multiples such as 0.05.
Limit precision locally
Save as demo_decimal_3.py:
from decimal import Decimal, getcontext, localcontext
original_precision = getcontext().prec
with localcontext() as context:
context.prec = 6
print("One seventh:", Decimal("1") / Decimal("7"))
print("Large value:", Decimal("12345") + Decimal("0.67"))
print("Precision restored:", getcontext().prec == original_precision)Run it from the directory where you saved it:
python3 demo_decimal_3.pyOutput:
One seventh: 0.142857
Large value: 12345.7
Precision restored: TruePrecision counts significant digits, not decimal places. Arithmetic can still round; repeating fractions do not become exact. localcontext() restores the previous context afterward. Choose enough precision for intermediate calculations before rounding the final result. Very large results may exceed the context’s capacity when quantized.
References
Acknowledgements
This post was created with assistance from AI.