tags:

views:

267

answers:

6

Kind of like this question, but in reverse.

Given a string like 1, 1/2, or 1 2/3, what's the best way to convert it into a float? I'm thinking about using regexes on a case-by-case basis, but perhaps someone knows of a better way, or a pre-existing solution. I was hoping I could just use eval, but I think the 3rd case prevents that.

+1  A: 

That might be a dirty workaround, but you could convert spaces to a + sign to solve the 3rd case (or to a - if your fraction is negative).

schnaader
+1  A: 

Depending on what syntax you want to support for your fractions, eval('+'.join(s.split())) (with true division in place -- i.e., Python 3 or from __future__ import division in Python 2 -- might work. It would cover all the cases you mention, in particular.

Alex Martelli
+2  A: 

Though you should stear clear of eval completely. Perhaps some more refined version of:

num,den = s.split( '/' )
wh, num = num.split()
result = wh + (float(num)/float(den))

Sorry, meant to be num.split not s.split, and casts. Edited.

Dave
+9  A: 

maybe something like this (2.6+)

from fractions import Fraction
float(sum(Fraction(s) for s in '1 2/3'.split()))
newacct
Some of these other solutions work too, but this one looks the most elegant. Works great! Thanks a ton.
Mark
Not only more elegant, but the most accurate too
Nadia Alramli
As Shnaader's answer pointed out, beware of negative signs.
jprete
+1  A: 

This implementation avoids using eval and works on pre-2.6 versions of Python.

# matches a string consting of an integer followed by either a divisor
# ("/" and an integer) or some spaces and a simple fraction (two integers
# separated by "/")
FRACTION_REGEX = re.compile(r'^(\d+)(?:(?:\s+(\d+))?/(\d+))?$')

def parse(x):
  i, n, d = FRACTION_REGEX.match(x).groups()
  if d is None: return i  # if d is None, then n is also None
  if n is None: i, n = 0, i
  return float(i) + float(n) / float(d)

To test:

>>> for x in ['1', '1/2', '1 2/3']: print parse(x)
... 
1
0.5
1.66666666667
Laurence Gonsalves
A: 
>>> s="1/2"
>>> eval('/'.join(map(str,map(float,s.split("/")))))
0.5

>>> s="3/5"
>>> eval('/'.join(map(str,map(float,s.split("/")))))
0.59999999999999998