1

我尝试了几种方法,我真的只关心性能,而不是正确性。我注意到基于正则表达式的实现比使用类型强制的实现慢 3-4 倍。还有另一种更有效的方法吗?

def IsNumber(x):
    try:
        _ = float(x)
    except ValueError:
        return False
    return True

 def IsNumber2(x):
     import re
     if re.match("^\d*.?\d*$", x) == None:
         return False
     return True

谢谢!

4

4 回答 4

6

首先,他们没有做同样的事情。例如,浮点数可以指定为“1e3”,float() 将接受它。这也不是强制,而是转换。

其次,不要在 IsNumber2 中导入 re,尤其是当您尝试将它与 timeit 一起使用时。在函数之外进行导入。

最后,float() 更快并不让我感到惊讶。这是一个用 C 语言编写的用于非常特定目的的专用例程,而正则表达式必须转换为可解释的形式。

您使用 float() 的第一个版本是否足够快?应该是这样,而且我不知道在 Python 中做同样事情的更好方法。

于 2010-02-11T22:24:26.317 回答
2

并不真地。强制是执行此操作的公认方式。

于 2010-02-11T22:20:16.793 回答
2

答案很大程度上取决于“数字字符串”的含义。如果您对数字字符串的定义是“浮点接受的任何内容”,那么很难改进 try-except 方法。

但请记住,float 可能比您想要的更自由:在大多数机器上,它会接受代表无穷大和 nans 的字符串。例如,在我的机器上,它接受'nan(dead!$#parrot)'. 它还将接受前导和尾随空格。根据您的应用程序,您可能希望排除浮点数的指数表示。在这些情况下,使用正则表达式是有意义的。要仅排除无穷大和 nan,使用 try-except 方法然后使用 math.isnan 和 math.isinf 检查转换结果可能会更快。

为数字字符串编写正确的正则表达式是一项非常容易出错的任务。例如,您的IsNumber2函数接受字符串'.'。您可以在十进制模块源中找到经过实战测试的数字字符串正则表达式版本。这是(有一些小的编辑):

_parser = re.compile(r"""        # A numeric string consists of:
    (?P<sign>[-+])?              # an optional sign, followed by either...
    (
        (?=\d|\.\d)              # ...a number (with at least one digit)
        (?P<int>\d*)             # having a (possibly empty) integer part
        (\.(?P<frac>\d*))?       # followed by an optional fractional part
        (E(?P<exp>[-+]?\d+))?    # followed by an optional exponent, or...
    |
        Inf(inity)?              # ...an infinity, or...
    |
        (?P<signal>s)?           # ...an (optionally signaling)
        NaN                      # NaN
        (?P<diag>\d*)            # with (possibly empty) diagnostic info.
    )
    \Z
""", re.VERBOSE | re.IGNORECASE | re.UNICODE).match

这几乎完全匹配 float 接受的内容,除了前导和尾随空格以及 nans 的一些细微差异(用于信号 nans 的额外 's' 和诊断信息)。当我需要一个数字正则表达式时,我通常从这个开始并编辑掉我不需要的位。

注意可以想象,浮点数可能比正则表达式慢,因为它不仅要解析字符串,还要将其转换为浮点数,这是一个相当复杂的计算;但是,如果是这样,那仍然会令人惊讶。

于 2010-02-11T23:36:38.143 回答
0

您可以先尝试编译正则表达式,但我想它仍然会更慢。

此外,如果您想知道您的字符串是否是一个数字,因为您要使用它进行计算,那么无论如何您都必须强制它。

于 2010-02-11T22:25:13.193 回答