将字符串转换为float而不进行静默NaN / Inf转换

时间:2010-06-05 15:12:34

标签: python floating-point

我想使用Python 2.6及更高版本将字符串转换为浮点数,但没有以静默方式将'NaN''Inf'之类的内容转换为浮动对象。我确实希望它们被默默地忽略,就像任何无效的浮动表示文本一样。

在2.6之前,float("NaN")会在Windows上引发ValueError。现在它返回一个float,math.isnan()返回True,这对我的应用程序来说没有用处。 (正如所指出的,这一直是一种依赖于平台的行为,但考虑到我的目的,无论发生在哪里,都认为这是一种不受欢迎的行为。)

这就是我现在所拥有的:

import math
def get_floats(source):
    for text in source.split():
        try:
            val = float(text)
            if math.isnan(val) or math.isinf(val):
                raise ValueError
            yield val
        except ValueError:
            pass

这是一个生成器,我可以提供包含表示实数的空格分隔序列的字符串。我希望它只产生那些纯粹是浮动数字表示的字段,如“1.23”或“-34e6”,但不是例如“NaN”或“-Inf”。根本不浮动的东西,例如“你好”,也应该被忽略。

测试用例:

assert list(get_floats('1.23 foo -34e6 NaN -Inf')) == [1.23, -34000000.0]

请提出您认为更优雅的替代方案,即使它们涉及“在您跳跃之前”(通常被认为是Python中较小的方法)。

编辑以澄清非浮动文本,例如“hello”也应该被忽略。目的是只取出那些真实数字而忽略其他一切的东西。

4 个答案:

答案 0 :(得分:2)

我是这样写的。我认为它结合了简洁性和可读性。

def is_finite(x):
    return not math.isnan(x) and not math.isinf(x)

def get_floats(source):
    for x in source.split():
        try:
            yield float(x)
        except ValueError:
            pass

def get_finite_floats(source):
    return (x for x in get_floats(source) if is_finite(x))

答案 1 :(得分:1)

这是一个非常小的建议,但continue比提出异常要快一点:

def get_floats(source):
    for text in source.split():
        try:
            val = float(text)
            if math.isnan(val) or math.isinf(val): continue
            yield val
        except ValueError:
            pass

使用raise ValueError

% python -mtimeit -s'import test' "list(test.get_floats('1.23 -34e6 NaN -Inf Hello'))"
10000 loops, best of 3: 22.3 usec per loop

使用continue

% python -mtimeit -s'import test' "list(test.get_floats_continue('1.23 -34e6 NaN -Inf Hello'))"
100000 loops, best of 3: 17.2 usec per loop

答案 2 :(得分:0)

我投了Paul Hankin的答案是为了提高可读性,但是如果我不想将代码分开,那么这里的原始变体就不那么笨重了。

def get_only_numbers(source):
    '''yield all space-separated real numbers in source string'''
    for text in source.split():
        try:
            val = float(text)
        except ValueError:
            pass  # ignore non-numbers
        else:
            # "NaN", "Inf" get converted: explicit test to ignore them
            if not math.isnan(val) and not math.isinf(val):
                yield val

与我原来的情况相差甚远。

答案 3 :(得分:0)

怎么样

[]