10

如何将可以表示十进制或有理数的字符串转换为浮点数

>>> ["0.1234", "1/2"]
['0.1234', '1/2']

我想要 [0.1234, 0.5]。

eval 是我的想法,但没有运气:

>>> eval("1/2")
0
4

10 回答 10

19

如果转换失败,我会解析字符串:

>>> def convert(s):
    try:
        return float(s)
    except ValueError:
        num, denom = s.split('/')
        return float(num) / float(denom)
...

>>> convert("0.1234")
0.1234

>>> convert("1/2")
0.5

通常使用 eval 是一个坏主意,因为它存在安全风险。特别是如果正在评估的字符串来自系统外部。

于 2009-02-22T22:18:47.247 回答
7

正如其他人指出的那样,使用eval是潜在的安全风险,而且肯定是一个坏习惯。(如果你不认为它有风险,exec想象一下eval:)__import__('os').system('rm -rf /')

但是,如果您有 python 2.6 或更高版本,则可以使用ast.literal_eval提供的字符串:

只能由以下 Python 文字结构组成:字符串、数字、元组、列表、字典、布尔值和无。

因此它应该是相当安全的:-)

于 2009-02-22T22:34:55.057 回答
7

另一个选项(也仅适用于 2.6 及更高版本)是fractions模块。

>>> from fractions import Fraction
>>> Fraction("0.1234")
Fraction(617, 5000)
>>> Fraction("1/2")
Fraction(1, 2)
>>> float(Fraction("0.1234"))
0.1234
>>> float(Fraction("1/2"))
0.5
于 2009-02-22T23:04:44.267 回答
4

用于from __future__ import division获得您想要的行为。然后,在紧要关头,你可以做类似的事情

from __future__ import division
strings = ["0.1234", "1/2", "2/3"]
numbers = map(eval, strings)

从字符串中获取浮点列表。如果您想以“正确”的方式执行此操作,请不要使用eval(),而是编写一个接受字符串并float()在它不包含斜杠时调用它的函数,或者解析字符串并在有斜杠时将分子和分母相除在里面。

一种方法:

def parse_float_string(x)
    parts = x.split('/', 1)
    if len(parts) == 1:
        return float(x)
    elif len(parts) == 2:
        return float(parts[0])/float(parts[1])
    else:
        raise ValueError

然后只会map(parse_float_string, strings)给你你的清单。

于 2009-02-22T22:16:05.367 回答
3

/运算符进行整数除法。尝试:

>>> eval("1.0*" + "1/2")
0.5

因为eval()具有潜在危险,您应该始终准确检查您传递给它的内容:

>>> import re
>>> s = "1/2"
>>> if re.match(r"\d+/\d+$", s):
...     eval("1.0*" + s)
...
0.5

但是,如果您首先将输入与正则表达式进行匹配,您不妨使用r"(\d+)/(\d+)$"提取分子和分母,自己进行除法,并完全避免eval()

>>> m = re.match(r"(\d+)/(\d+)$", s)
>>> if m:
...     float(m.group(1)) / float(m.group(2))
...
0.5
于 2009-02-22T22:13:30.990 回答
2

eval 的问题在于,就像在 python 中一样,整数的商是一个整数。所以,你有几个选择。

第一个是简单地使整数除法返回浮点数:

from __future__ import division

另一种是拆分有理数:

reduce(lambda x, y: x*y, map(int, rat_str.split("/")), 1)

其中 rat_str 是有理数的字符串。

于 2009-02-22T22:17:37.360 回答
1

在 Python 3 中,这应该可以工作。

>>> x = ["0.1234", "1/2"]
>>> [eval(i) for i in x]
[0.1234, 0.5]
于 2009-02-23T00:18:53.903 回答
1

sympy可以在这里为您提供帮助:

import sympy

half = sympy.Rational('1/2')
p1234 = sympy.Rational('0.1234')
print '%f, %f" % (half, p1234)
于 2009-02-23T02:54:20.767 回答
0

这是因为 1 和 2 被 Python 解释为整数而不是浮点数。它需要是 1.0/2.0 或两者的混合。

于 2009-02-22T22:15:39.750 回答
0

from __future__ import division与结合的建议eval肯定会奏效。

可能值得指出的是,不使用eval而是解析字符串的建议这样做eval是危险的:如果有某种方式可以将任意字符串发送到eval,那么您的系统很容易受到攻击。所以这是一个坏习惯。(但如果这只是快速而肮脏的代码,那可能没什么大不了的!)

于 2009-02-22T22:29:11.513 回答