decimal: Mixing With float Raises on Arithmetic, Not on Comparison (tested)
Python's decimal module famously refuses to let you add a Decimal and a float directly, forcing you to convert explicitly -- a safety net against silently mixing exact and imprecise numbers. We measured whether that same protection extends to comparison operators and sorted(), which also mix the two types.
1. Arithmetic between Decimal and float raises TypeError
from decimal import Decimal
try:
Decimal("0.1") + 0.1
except TypeError as e:
print("TypeError:", e)
TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'
Measured: adding a Decimal and a float raises immediately -- this is the well-known, intentional guard rail. It forces an explicit choice: convert the float to Decimal (and decide whether via str() or from_float()) before combining them.
2. Comparison between Decimal and float runs silently -- and can give a surprising answer
from decimal import Decimal
print(Decimal("0.1") == 0.1)
print(Decimal("0.1") < 0.10000000000000001)
False
True
Measured: no TypeError here -- == and < between Decimal and float work without complaint. But Decimal('0.1') == 0.1 is False (the float 0.1 isn't exactly 0.1, the same binary-imprecision issue as constructing Decimal(0.1) directly), and Decimal('0.1') compares as strictly less than a float that's supposed to represent an even tinier increment above it, because the comparison silently uses the float's imprecise binary value. Unlike arithmetic, there's no error to signal that a precision-sensitive mismatch just happened.
3. sorted() and list membership inherit the same silent mixing
from decimal import Decimal
mixed = [Decimal("0.3"), 0.1, Decimal("0.2")]
print(sorted(mixed))
[0.1, Decimal('0.2'), Decimal('0.3')]
Measured: sorted() on a list mixing Decimal and float values runs without error and produces a plausible-looking, correctly-ordered result here -- but it did so by comparing a Decimal against a float at every step, the exact operation that silently uses the float's imprecise value. A codebase that got a loud TypeError the first time it tried to add a stray float into Decimal-typed data can still have that same stray float pass through comparisons, sorting, and filtering completely unnoticed, carrying its imprecision into every comparison it's part of. Convert floats to Decimal at the boundary where they enter the system, rather than relying on arithmetic errors to catch every place a float might leak in -- comparisons won't catch it for you.
Frequently asked questions
Does Python's decimal module allow comparing a Decimal to a float?
Yes, measurably -- unlike arithmetic (+, -, *, /), which raises TypeError when mixing Decimal and float, comparison operators (==, <, >, etc.) and functions like sorted() run without error on mixed Decimal/float values.
Why does Decimal('0.1') + 0.1 raise an error but Decimal('0.1') == 0.1 doesn't?
Decimal intentionally blocks arithmetic with float to force an explicit, deliberate conversion, avoiding silent precision loss. We measured that this protection doesn't extend to comparisons -- == and < between Decimal and float are permitted and use the float's imprecise binary value directly.
Is Decimal('0.1') == 0.1 True or False in Python?
False -- we measured this directly. The float 0.1 is a binary approximation, not the exact value 0.1, so comparing it against the exact Decimal('0.1') correctly reports them as unequal, but silently (no error) rather than via the loud TypeError you'd get from trying to add them.
Can sorted() silently mix Decimal and float values?
Yes -- we measured sorted() on a list containing both Decimal and float values running without error, using the same imprecision-prone comparison that arithmetic would have rejected. A stray float in otherwise-Decimal data can pass through sorting and filtering undetected.
How do I prevent floats from silently leaking into Decimal comparisons?
Convert every float to Decimal (via str(), not the float constructor directly) at the point it enters your system, rather than relying on errors to catch mixed types later -- we confirmed comparisons and sorted() give no error signal when a float is present, unlike arithmetic.
Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in decimal module: added a Decimal and a float together, then compared and sorted the same mixed pair, to see whether decimal's protection against mixing types with float applies equally to arithmetic and comparison. PlainHeaders is our extension; Python's decimal module is built in.