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!
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')