Преобразовать фракцию в float?
Вид как этот вопрос, но наоборот.
Для строки типа 1
, 1/2
или 1 2/3
, какой лучший способ преобразовать ее в float? Я думаю об использовании регулярных выражений в каждом конкретном случае, но, возможно, кто-то знает о лучшем способе или уже существующем решении. Я надеялся, что могу просто использовать eval
, но я думаю, что 3-й случай предотвращает это.
Ответы
Ответ 1
Я немного изменил ответ Джеймса.
def convert_to_float(frac_str):
try:
return float(frac_str)
except ValueError:
num, denom = frac_str.split('/')
try:
leading, num = num.split(' ')
whole = float(leading)
except ValueError:
whole = 0
frac = float(num) / float(denom)
return whole - frac if whole < 0 else whole + frac
print convert_to_float('3') # 3.0
print convert_to_float('3/2') # 1.5
print convert_to_float('1 1/2') # 1.5
print convert_to_float('-1 1/2') # -1.5
http://ideone.com/ItifKv
Ответ 2
может быть что-то вроде этого (2.6 +)
from fractions import Fraction
float(sum(Fraction(s) for s in '1 2/3'.split()))
Ответ 3
Хотя вы должны полностью избавиться от eval. Возможно, еще более утонченная версия:
num,den = s.split( '/' )
wh, num = num.split()
result = wh + (float(num)/float(den))
Извините, это означает, что num.split не s.split, а casts. Ред.
Ответ 4
Это может быть грязное обходное решение, но вы можете преобразовать пробелы в знак +
для решения 3-го случая (или для -
, если ваша доля отрицательна).
Ответ 5
Я вижу, что здесь уже есть несколько хороших ответов, но мне повезло с этим. Это также имеет то преимущество, что он будет терпеть недробные строки, если вы разбираете смешанные наборы данных, поэтому нет необходимости проверять, является ли это строкой нити или нет.
def convert_to_float(frac_str):
try:
return float(frac_str)
except ValueError:
try:
num, denom = frac_str.split('/')
except ValueError:
return None
try:
leading, num = num.split(' ')
except ValueError:
return float(num) / float(denom)
if float(leading) < 0:
sign_mult = -1
else:
sign_mult = 1
return float(leading) + sign_mult * (float(num) / float(denom))
>>> convert_to_float('3')
3.0
>>> convert_to_float('1/4')
0.25
>>> convert_to_float('1 2/3')
1.6666666666666665
>>> convert_to_float('-2/3')
-0.6666666666666666
>>> convert_to_float('-3 1/2')
-3.5
Ответ 6
def fractionToFloat(fraction):
num = 0
mult = 1
if fraction[:1] == "-":
fraction = fraction[1:]
mult = -1
if " " in fraction:
a = fraction.split(" ")
num = float(a[0])
toSplit = a[1]
else:
toSplit = fraction
frac = toSplit.split("/")
num += float(frac[0]) / float(frac[1])
return num * mult
Он также может обрабатывать "2 1/1e-8", "-1/3" и "1/5e3".
Ответ 7
Эта реализация позволяет избежать использования eval и работает с версиями Python до версии 2.6.
# 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)
Чтобы проверить:
>>> for x in ['1', '1/2', '1 2/3']: print parse(x)
...
1
0.5
1.66666666667
Ответ 8
В зависимости от того, какой синтаксис вы хотите поддерживать для своих фракций, eval('+'.join(s.split()))
(с истинным делением на место - то есть, Python 3 или from __future__ import division
в Python 2 - может работать. Он будет охватывать все случаи, которые вы упоминаете, в частности.
Ответ 9
>>> 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