pythondecimalstandard-libraryfractions

# Best way to convert fractions.Fraction to decimal.Decimal?

In Python, the `fractions.Fraction` and `decimal.Decimal` standard library classes exist to help keep arithmetic with rational numbers precise. For the unfamiliar, an example of where it helps:

``````>>> 1 / 10 * 3
0.30000000000000004
>>> decimal.Decimal('1') / 10 * 3
Decimal('0.3')
>>> fractions.Fraction('1') / 10 * 3
Fraction(3, 10)
``````

My question is, if I have a `Fraction`, what's the best way to convert it to a `Decimal`?

Unfortunately the obvious solution doesn't work:

``````>>> decimal.Decimal(fractions.Fraction(3, 10))
Traceback (most recent call last):
...
TypeError: conversion from Fraction to Decimal is not supported
``````

Right now I'm using this code:

``````>>> decimal.Decimal(float(fractions.Fraction(3, 10)))
Decimal('0.299999999999999988897769753748434595763683319091796875')
``````

Now, when I actually output this value, any amount of rounding will convert it to 0.3, and I only do this conversion immediately before output (all the core math is done with `Fraction`). Still, it seems a bit silly to me that I can't get a `Decimal('0.3')` from a `Fraction(3, 10)`. Any help would be appreciated!

Solution

• How about leaving the division of the fraction to `Decimal()` itself?

``````def decimal_from_fraction(frac):
return frac.numerator / decimal.Decimal(frac.denominator)
``````

This is what `Fraction.__float__()` does (simply divide the numerator by the denominator), but by turning at least one of the two values into a `Decimal` object you get to control the output.

This lets you use the `decimal` context:

``````>>> decimal_from_fraction(fractions.Fraction(3, 10))
Decimal('0.3')
>>> decimal_from_fraction(fractions.Fraction(1, 55))
Decimal('0.01818181818181818181818181818')
>>> with decimal.localcontext() as ctx:
...    ctx.prec = 4
...    decimal_from_fraction(fractions.Fraction(1, 55))
...
Decimal('0.01818')
``````