views:

30

answers:

2

I have this function inside another function:

def _sum(k):
        return sum([(-1) ** v * fractions.Fraction(str(bin_coeff(k, v))) * fractions.Fraction((n + v) ** m, k + 1) for v in xrange(k + 1)])

When i call fractions.Fraction on bin_coeff it reports me this error:

ValueError: Invalid literal for Fraction: '1.05204948186e+12'

How can can I convert a float in that form into a Fraction object?

Is there a better solution than:

fractions.Fraction(*bin_coeff(k, v).as_integer_ratio())

Thank you,
rubik

P.S. bin_coeff always returns a float

+1  A: 

I cannot reproduce your error in py3k, but you could pass your float straight to from_float class method:

>>> fractions.Fraction.from_float(1.05204948186e+12)
Fraction(1052049481860, 1)
SilentGhost
I'm running Python 2.6: `fractions.Fraction('1.05204948186e+12')ValueError: Invalid literal for Fraction: '1.05204948186e+12'` but from_float works, thanks
rubik
@rubik: you still could use `from_float` method
SilentGhost
Ok, I will use that. Thanks!
rubik
+1  A: 

If you're curious, this is due (as you might expect) to the Fraction regex in fractions.py:

_RATIONAL_FORMAT = re.compile(r"""
    \A\s*                      # optional whitespace at the start, then
    (?P<sign>[-+]?)            # an optional sign, then
    (?=\d|\.\d)                # lookahead for digit or .digit
    (?P<num>\d*)               # numerator (possibly empty)
    (?:                        # followed by an optional
       /(?P<denom>\d+)         # / and denominator
    |                          # or
       \.(?P<decimal>\d*)      # decimal point and fractional part
    )?
    \s*\Z                      # and optional whitespace to finish
""", re.VERBOSE)

which doesn't match floats in scientific notation. This was changed in Python 2.7 (the following is from 3.1 because I don't have 2.7 installed):

_RATIONAL_FORMAT = re.compile(r"""
    \A\s*                      # optional whitespace at the start, then
    (?P<sign>[-+]?)            # an optional sign, then
    (?=\d|\.\d)                # lookahead for digit or .digit
    (?P<num>\d*)               # numerator (possibly empty)
    (?:                        # followed by
       (?:/(?P<denom>\d+))?    # an optional denominator
    |                          # or
       (?:\.(?P<decimal>\d*))? # an optional fractional part
       (?:E(?P<exp>[-+]?\d+))? # and optional exponent
    )
    \s*\Z                      # and optional whitespace to finish
""", re.VERBOSE | re.IGNORECASE)
katrielalex
Thank you! It's very interesting!
rubik