Конвертировать дробь в плавающую? - PullRequest
23 голосов
/ 27 ноября 2009

Вид , как этот вопрос , но в обратном порядке.

Учитывая строку типа 1, 1/2 или 1 2/3, как лучше всего преобразовать ее в число с плавающей точкой? Я думаю об использовании регулярных выражений в каждом конкретном случае, но, возможно, кто-то знает о лучшем способе или уже существующем решении. Я надеялся, что смогу просто использовать eval, но я думаю, что третий случай предотвращает это.

Ответы [ 9 ]

36 голосов
/ 27 ноября 2009

может быть как то так (2.6 +)

from fractions import Fraction
float(sum(Fraction(s) for s in '1 2/3'.split()))
8 голосов
/ 03 июня 2015

Я подправил Джеймс ответил немного.

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

6 голосов
/ 27 ноября 2009

Хотя вы должны полностью избегать eval. Возможно, какая-то более изысканная версия:

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

Извините, предполагается, что num.split не s.split, а забрасывает. Edited.

3 голосов
/ 29 сентября 2013

Я вижу, что здесь уже есть несколько хороших ответов, но мне повезло с этим. Он также имеет то преимущество, что допускает строки без дробей, если вы анализируете смешанные наборы данных, поэтому нет необходимости проверять, является ли строка дробью или нет.

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
2 голосов
/ 24 сентября 2014
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».

2 голосов
/ 27 ноября 2009

Эта реализация избегает использования 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: n, d = 0, 1  # 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(repr(parse(x)))
... 
1.0
0.5
1.6666666666666665
2 голосов
/ 27 ноября 2009

Это может быть грязный обходной путь, но вы можете преобразовать пробелы в знак +, чтобы решить третий случай (или в -, если ваша дробь отрицательна).

0 голосов
/ 27 ноября 2009
>>> 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
0 голосов
/ 27 ноября 2009

В зависимости от того, какой синтаксис вы хотите поддерживать для своих фракций, eval('+'.join(s.split())) (с истинным делением на месте - то есть Python 3 или from __future__ import division в Python 2) - может работать. Это будет охватывать все случаи, которые вы упомянули в частности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...