如何在Python中检查字符串是否可以转换为浮点数?

28

有没有类似于 str.isnumeric 的函数,但适用于浮点数?

'13.37'.isnumeric() #False  

我仍然使用这个:

def isFloat(string):
    try:
        float(string)
        return True
    except ValueError:
        return False

一个更一致和完整的答案:` def strType(xstr): try: int(xstr) return 'int' except: try: float(xstr) return 'float' except: try: complex(xstr) return 'complex' except: return 'str'print("4", strType("4")) print("12345678901234567890", strType("12345678901234567890")) print("4.1", strType("4.1")) print("4.1+3j", strType("4.1+3j")) print("a", strType("a")) ` - juanfal
3
'13.37'.replace(".","").isnumeric(): - Grigory Ilizirov
我最喜欢@GrigoryIlizirov的答案,因为它不会引发异常。 - Nigel Feasey
6个回答

12

正如Imran所说,你的代码展示得非常好。

不过,它会导致isFloat的客户端沿着“先看再跳”而非更符合Python编程思想的“宁愿请求原谅,也不必事先获准”的道路前进。

对于客户端而言,更符合Python编程思想的方法是假设它们拥有一个表示浮点数的字符串,但随时准备处理如果不是浮点数会抛出的异常。

这种方法还可以很好地将字符串转换为浮点数,只需要进行一次转换即可。


4
请不要浪费时间写这样的内容。只需编写您真正的应用程序。如果出现 ValueError,则意味着输入不是有效的浮点数,并且整体异常处理程序可以报告此情况。没有必要预先检查浮点值,因为 float 函数会在需要时正确执行此操作。而且总是正确的。 - S.Lott
虽然我理解try catch的作用,但我认为频繁使用它可能会导致处理异常的成本增加。我很惊讶isfloat助手不可用。 - Peter Moore
@S.Lott 这并不一定是正确的。当你需要根据未知值做出决策时,这种函数非常有用。这样更易读。 - Nilpo

4

更全面的概括:

    def strType(xstr):
        try:
            int(xstr)
            return 'int'
        except:
            try:
                float(xstr)
                return 'float'
            except:
                try:
                    complex(xstr)
                    return 'complex'
                except:
                    return 'str'


    print("4", strType("4"))
    print("12345678901234567890", strType("12345678901234567890"))
    print("4.1", strType("4.1"))
    print("4.1+3j", strType("4.1+3j"))
    print("a", strType("a"))

2

您的代码绝对没问题。基于正则表达式的解决方案更容易出错。

使用timeit进行快速测试后,发现float(str_val)确实比re.match()更快。

>>> timeit.timeit('float("-1.1")')
1.2833082290601467
>>> timeit.timeit(r"pat.match('-1.1')", "import re; pat=re.compile(r'^-?\d*\.?\d+(?:[Ee]-?\d+)?$');")
1.5084138986904527

以上使用的正则表达式有一个缺陷,它无法匹配'-1.',虽然float()函数可以将其转换为正确的浮点数值。


我认为这不是Python的方式——用6行代码解决常见问题。但还是谢谢。 - Andrew
2
@Imran:你的性能比较不正确,虽然 float 会更快,但是你需要在执行循环之外编译正则表达式,它需要被重复使用才能实现实用性。 - SilentGhost
编译后的正则表达式性能甚至更差:P。这怎么可能呢?timeit.timeit中的setup语句只被评估一次,不是吗? - Imran
@SilentGhost:谢谢,现在正则表达式的性能更接近于“float” :) - Imran
当isFloat()失败时怎么办?抛出和捕获异常/错误需要多长时间? - Silveri
显示剩余5条评论

1

不过有一个小问题: float('nan') 返回 nan,没有引发任何异常 ;)


1
naninf(正数和负数)是浮点数,如1.e9GNU libcIEEE 754...所以这是有效的。 - bufh

0

延伸自@Imran的结果:

>>> timeit('float("-1.1")', number=10000000)
1.365271806716919

>>> timeit(r"isfloat('-1.1')", """def isfloat(s): t = s.partition('.');
           return t[1] and t[0].isdigit() and (not t[2] or t[2].isdigit());""",
           number=10000000)
2.565232992172241

>>> timeit(r"pat.match('-1.1')", "import re; pat=re.compile(r'^-?\d*\.?\d+(
    ...: ?:[Ee]-?\d+)?$');", number=10000000)
3.258622169494629

我的partition解决方案比正则表达式快,但比float慢;然而它的优点是不会引发错误(因此您可以在例如:理解中使用它)。

这可以处理像1.这样的边缘情况,但不能处理像NaN这样的特殊情况。


-2

isinstance(myVariable, float) 如果你要测试一个浮点数变量,这个方法会起作用。

编辑:说得太早了,没有完全理解你想要的内容。


2
这不是 OP 想要的。 - SilentGhost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接