On Fri, Oct 09, 2020 at 03:53:24AM +1100, Chris Angelico wrote:
On Fri, Oct 9, 2020 at 3:43 AM Steven D'Aprano <steve@pearwood.info> wrote:
On Thu, Oct 08, 2020 at 11:58:04AM -0400, Random832 wrote:
I was making a "convert Fraction to Decimal, exactly if possible" function and ran into a wall: it's not possible to do some of the necessary operations with exact precision in decimal:
Of course you can't do them with *exact* precision in Decimal, because that only has a fixed precision. (User-configurable, but fixed.)
py> from decimal import Decimal py> from fractions import Fraction py> x = Fraction(1, 3) py> Decimal(x.numerator)/x.denominator Decimal('0.3333333333333333333333333333')
You trimmed off the part where the OP said that the denominator would be only multiples of 2 and/or 5 :)
I trimmed it because I didn't understand the relevance. If the denominator is an exact multiple of only 2 and 5, then I think the conversion will be exact if the precision is sufficient.
Fraction(1, 2) ** 53 * Fraction(1, 5) ** 47 Fraction(1, 6400000000000000000000000000000000000000000000000) Decimal("314159265358979323") / _.denominator Decimal('4.908738521234051921875E-32')
In theory, this should be precisely representable in decimal, but how many digits would you need?
The brute force way of doing that will be to trap on Inexact and do the division. If it succeeds, you are done; otherwise double the precision and try again. Repeat until you either succeed, or reach the maximum possible precision. I don't know of any clever way of predicting the number of decimal places a fraction will take as a decimal short of actually doing the division. It does not depend on only the denominator, you also need to know the numerator: Decimal(1/4) # requires 2 decimal places Decimal(2/4) # requires only 1 decimal place -- Steve