S
Steven D'Aprano
I have a need to convert arbitrary non-complex numbers into numerator/
denominator pairs. Numbers could be ints, floats, Fractions or Decimals.
For example:
2 => (2, 1)
0.25 => (1, 4)
Fraction(2, 3) => (2, 3)
Decimal("0.5") => (1, 2)
The first three cases are easy and fast:
# ints and Fractions
number.numerator, number.denominator
# floats are a little slower
number.as_integer_ratio()
But Decimals are unfortunately slower. MUCH slower, about 40 times slower
than Fractions in Python 3.3:
tmp = Fraction.from_decimal(number)
(tmp.numerator, tmp.denominator)
This ends up being the bottleneck in my code: once you include the
scaffolding code to select the right conversion method, processing a
large list of Decimals is about fifty times slower than large lists of
floats or fractions.
Is there a fast way to convert a Decimal into a pair of numbers numerator/
denominator? It *must* be exact, but it doesn't have to be simplest form.
For example, Decimal("0.5") => (5, 10) would be okay, although (1, 2)
would be preferred.
I've tried this function:
def convert(d):
sign, digits, exp = d.as_tuple()
num = int(''.join([str(digit) for digit in digits]))
if sign: num = -num
return num, 10**-exp
which is faster, but not fast enough. Any suggestions?
denominator pairs. Numbers could be ints, floats, Fractions or Decimals.
For example:
2 => (2, 1)
0.25 => (1, 4)
Fraction(2, 3) => (2, 3)
Decimal("0.5") => (1, 2)
The first three cases are easy and fast:
# ints and Fractions
number.numerator, number.denominator
# floats are a little slower
number.as_integer_ratio()
But Decimals are unfortunately slower. MUCH slower, about 40 times slower
than Fractions in Python 3.3:
tmp = Fraction.from_decimal(number)
(tmp.numerator, tmp.denominator)
This ends up being the bottleneck in my code: once you include the
scaffolding code to select the right conversion method, processing a
large list of Decimals is about fifty times slower than large lists of
floats or fractions.
Is there a fast way to convert a Decimal into a pair of numbers numerator/
denominator? It *must* be exact, but it doesn't have to be simplest form.
For example, Decimal("0.5") => (5, 10) would be okay, although (1, 2)
would be preferred.
I've tried this function:
def convert(d):
sign, digits, exp = d.as_tuple()
num = int(''.join([str(digit) for digit in digits]))
if sign: num = -num
return num, 10**-exp
which is faster, but not fast enough. Any suggestions?