decimal and fractions: Constructor Support Only Goes One Way (tested)
Fraction and Decimal both represent exact values, so it's natural to expect their constructors to convert either way. We measured both directions and found the support is one-sided: Fraction accepts a Decimal directly, but Decimal refuses a Fraction.
1. Fraction's constructor accepts a Decimal directly
from decimal import Decimal
from fractions import Fraction
print(Fraction(Decimal("0.1")))
1/10
Measured: Fraction(Decimal("0.1")) converts cleanly to the exact fraction 1/10 -- no error, and no float-style imprecision, since Decimal's own value is already exact.
2. Decimal's constructor refuses a Fraction with TypeError
from decimal import Decimal
from fractions import Fraction
try:
Decimal(Fraction(1, 2))
except TypeError as e:
print("TypeError:", e)
TypeError: conversion from Fraction to Decimal is not supported
Measured: the reverse conversion raises TypeError with a message that spells out exactly what's missing -- decimal's C implementation has no code path for a Fraction argument, even though it does support int and str arguments, and Fraction itself is happy to accept a Decimal.
3. Going through float loses exactness -- it isn't a safe workaround
from decimal import Decimal
from fractions import Fraction
f = Fraction(1, 3)
print(Decimal(float(f)))
0.333333333333333314829616256247390992939472198486328125
Measured: routing a Fraction through float() before handing it to Decimal() "works" in the sense that it doesn't raise, but it bakes in float's binary rounding error first -- Fraction(1, 3) becomes a long, inexact decimal rather than a clean repeating-decimal placeholder. Decimal has no constructor path that preserves a Fraction's exactness at all, since a general fraction like 1/3 has no finite decimal representation. The practical takeaway: a function that accepts "any exact numeric type" and normalizes everything to Decimal will crash the moment a Fraction reaches it directly (TypeError, easy to catch in testing), but will silently succeed with corrupted precision if the caller "helpfully" converts through float first (much harder to catch) -- if a Fraction needs to become a Decimal, convert through its numerator and denominator explicitly (e.g. Decimal(f.numerator) / Decimal(f.denominator) at whatever precision the context requires) rather than through float.
Frequently asked questions
Can you construct a Decimal directly from a Fraction in Python?
No -- we measured Decimal(Fraction(1, 2)) raising TypeError: conversion from Fraction to Decimal is not supported. The decimal module's constructor has no code path for a Fraction argument.
Can you construct a Fraction directly from a Decimal in Python?
Yes -- we measured Fraction(Decimal("0.1")) returning the exact fraction 1/10 with no error. The support only goes this one direction, not the reverse.
What's a safe way to convert a Fraction to a Decimal without raising TypeError?
Don't route it through float() first -- that bakes in float's binary rounding error (we measured Decimal(float(Fraction(1,3))) producing a long inexact digit string). Instead divide the numerator and denominator as Decimals explicitly, e.g. Decimal(f.numerator) / Decimal(f.denominator), inside a context with the precision you need.
Why does Decimal(Fraction(1, 2)) raise TypeError when Decimal accepts int and str?
The decimal module's constructor only implements conversion paths for a specific set of types (int, str, float via from_float, tuples, other Decimals) -- Fraction isn't one of them, even though logically it represents an exact value just like Decimal does. We confirmed this is a clean TypeError, not a silent fallback.
Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in fractions and decimal modules: constructed a Fraction directly from a Decimal, then attempted the reverse, constructing a Decimal directly from a Fraction. PlainHeaders is our extension; Python's fractions and decimal modules are built in.