代码之家  ›  专栏  ›  技术社区  ›  Chris Upchurch

检查字符串是否可以在python中转换为float

  •  128
  • Chris Upchurch  · 技术社区  · 17 年前

    我有一些python代码,运行在字符串列表中,如果可能的话,将它们转换为整数或浮点数。对整数执行此操作非常简单

    if element.isdigit():
      newelement = int(element)
    

    浮点数比较困难。现在我正在使用 partition('.') 分开绳子并检查以确保一个或两个边都是数字。

    partition = element.partition('.')
    if (partition[0].isdigit() and partition[1] == '.' and partition[2].isdigit()) 
        or (partition[0] == '' and partition[1] == '.' and partition[2].isdigit()) 
        or (partition[0].isdigit() and partition[1] == '.' and partition[2] == ''):
      newelement = float(element)
    

    这是可行的,但很明显,如果这样做的话,那是有点小题大做。我考虑的另一个解决方案是将转换包装在一个try/catch块中,然后查看它是否成功,如中所述。 this question .

    有人有其他想法吗?对分割和尝试/捕获方法的相对优点有何看法?

    13 回复  |  直到 7 年前
        1
  •  217
  •   dbr    17 年前

    我就用……

    try:
        float(element)
    except ValueError:
        print "Not a float"
    

    …很简单,而且很有效

    另一个选项是正则表达式:

    import re
    if re.match("^\d+?\.\d+?$", element) is None:
        print "Not float"
    
        2
  •  138
  •   Mad Physicist    9 年前

    检查浮动的python方法:

    def isfloat(value):
      try:
        float(value)
        return True
      except ValueError:
        return False
    

    别被藏在游船里的妖精咬了!进行单元测试!

    什么是浮动的,不是浮动的,可能会让你吃惊:

    Command to parse                        Is it a float?  Comment
    --------------------------------------  --------------- ------------
    print(isfloat(""))                      False
    print(isfloat("1234567"))               True 
    print(isfloat("NaN"))                   True            nan is also float
    print(isfloat("NaNananana BATMAN"))     False
    print(isfloat("123.456"))               True
    print(isfloat("123.E4"))                True
    print(isfloat(".1"))                    True
    print(isfloat("1,234"))                 False
    print(isfloat("NULL"))                  False           case insensitive
    print(isfloat(",1"))                    False           
    print(isfloat("123.EE4"))               False           
    print(isfloat("6.523537535629999e-07")) True
    print(isfloat("6e777777"))              True            This is same as Inf
    print(isfloat("-iNF"))                  True
    print(isfloat("1.797693e+308"))         True
    print(isfloat("infinity"))              True
    print(isfloat("infinity and BEYOND"))   False
    print(isfloat("12.34.56"))              False           Two dots not allowed.
    print(isfloat("#56"))                   False
    print(isfloat("56%"))                   False
    print(isfloat("0E0"))                   True
    print(isfloat("x86E0"))                 False
    print(isfloat("86-5"))                  False
    print(isfloat("True"))                  False           Boolean is not a float.   
    print(isfloat(True))                    True            Boolean is a float
    print(isfloat("+1e1^5"))                False
    print(isfloat("+1e1"))                  True
    print(isfloat("+1e1.3"))                False
    print(isfloat("+1.3P1"))                False
    print(isfloat("-+1"))                   False
    print(isfloat("(1)"))                   False           brackets not interpreted
    
        3
  •  11
  •   Allan Pereira user936414    10 年前
    '1.43'.replace('.','',1).isdigit()
    

    哪个会回来 true 只有当数字串中有一个或没有“.”时。

    '1.4.3'.replace('.','',1).isdigit()
    

    将返回 false

    '1.ww'.replace('.','',1).isdigit()
    

    将返回

        4
  •  5
  •   Community Mohan Dere    9 年前

    如果您关心性能(我并不是建议您应该这样做),那么基于try的方法显然是赢家(与基于分区的方法或regexp方法相比),只要您不期望有很多无效字符串,在这种情况下,它可能会变慢(可能是由于异常处理的成本)。

    再说一次,我不是建议你关心性能,只是给你数据,以防你每秒做100亿次,或者其他什么。另外,基于分区的代码没有处理至少一个有效的字符串。

    $ ./floatstr.py
    F..
    partition sad: 3.1102449894
    partition happy: 2.09208488464
    ..
    re sad: 7.76906108856
    re happy: 7.09421992302
    ..
    try sad: 12.1525540352
    try happy: 1.44165301323
    .
    ======================================================================
    FAIL: test_partition (__main__.ConvertTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "./floatstr.py", line 48, in test_partition
        self.failUnless(is_float_partition("20e2"))
    AssertionError
    
    ----------------------------------------------------------------------
    Ran 8 tests in 33.670s
    
    FAILED (failures=1)
    

    这是代码(python 2.6,regexp取自john gietzen的 answer ):

    def is_float_try(str):
        try:
            float(str)
            return True
        except ValueError:
            return False
    
    import re
    _float_regexp = re.compile(r"^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$")
    def is_float_re(str):
        return re.match(_float_regexp, str)
    
    
    def is_float_partition(element):
        partition=element.partition('.')
        if (partition[0].isdigit() and partition[1]=='.' and partition[2].isdigit()) or (partition[0]=='' and partition[1]=='.' and pa\
    rtition[2].isdigit()) or (partition[0].isdigit() and partition[1]=='.' and partition[2]==''):
            return True
    
    if __name__ == '__main__':
        import unittest
        import timeit
    
        class ConvertTests(unittest.TestCase):
            def test_re(self):
                self.failUnless(is_float_re("20e2"))
    
            def test_try(self):
                self.failUnless(is_float_try("20e2"))
    
            def test_re_perf(self):
                print
                print 're sad:', timeit.Timer('floatstr.is_float_re("12.2x")', "import floatstr").timeit()
                print 're happy:', timeit.Timer('floatstr.is_float_re("12.2")', "import floatstr").timeit()
    
            def test_try_perf(self):
                print
                print 'try sad:', timeit.Timer('floatstr.is_float_try("12.2x")', "import floatstr").timeit()
                print 'try happy:', timeit.Timer('floatstr.is_float_try("12.2")', "import floatstr").timeit()
    
            def test_partition_perf(self):
                print
                print 'partition sad:', timeit.Timer('floatstr.is_float_partition("12.2x")', "import floatstr").timeit()
                print 'partition happy:', timeit.Timer('floatstr.is_float_partition("12.2")', "import floatstr").timeit()
    
            def test_partition(self):
                self.failUnless(is_float_partition("20e2"))
    
            def test_partition2(self):
                self.failUnless(is_float_partition(".2"))
    
            def test_partition3(self):
                self.failIf(is_float_partition("1234x.2"))
    
        unittest.main()
    
        5
  •  5
  •   SethMMorton    8 年前

    DR :

    • 如果您的输入主要是字符串, 可以 转换为浮点数, try: except: 方法是最好的本地python方法。
    • 如果您的输入主要是字符串, 不能 如果转换为float,正则表达式或分区方法会更好。
    • 如果您1)不确定您的输入或需要更高的速度和2)不介意,可以安装第三方C扩展, fastnumbers 效果很好。

    还有另一种方法可以通过第三方模块调用 快速数字 (公开,我是作者);它提供一个函数 isfloat . 我以Jacob Gabrielson在 this answer ,但增加了 fastnumbers.isfloat 方法。我还应该注意到,Jacob的例子没有对regex选项做出公正的解释,因为该示例中的大部分时间都是在全局查找中花费的,因为点运算符……我修改了这个函数,以便对 尝试:除: .


    def is_float_try(str):
        try:
            float(str)
            return True
        except ValueError:
            return False
    
    import re
    _float_regexp = re.compile(r"^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$").match
    def is_float_re(str):
        return True if _float_regexp(str) else False
    
    def is_float_partition(element):
        partition=element.partition('.')
        if (partition[0].isdigit() and partition[1]=='.' and partition[2].isdigit()) or (partition[0]=='' and partition[1]=='.' and partition[2].isdigit()) or (partition[0].isdigit() and partition[1]=='.' and partition[2]==''):
            return True
        else:
            return False
    
    from fastnumbers import isfloat
    
    
    if __name__ == '__main__':
        import unittest
        import timeit
    
        class ConvertTests(unittest.TestCase):
    
            def test_re_perf(self):
                print
                print 're sad:', timeit.Timer('ttest.is_float_re("12.2x")', "import ttest").timeit()
                print 're happy:', timeit.Timer('ttest.is_float_re("12.2")', "import ttest").timeit()
    
            def test_try_perf(self):
                print
                print 'try sad:', timeit.Timer('ttest.is_float_try("12.2x")', "import ttest").timeit()
                print 'try happy:', timeit.Timer('ttest.is_float_try("12.2")', "import ttest").timeit()
    
            def test_fn_perf(self):
                print
                print 'fn sad:', timeit.Timer('ttest.isfloat("12.2x")', "import ttest").timeit()
                print 'fn happy:', timeit.Timer('ttest.isfloat("12.2")', "import ttest").timeit()
    
    
            def test_part_perf(self):
                print
                print 'part sad:', timeit.Timer('ttest.is_float_partition("12.2x")', "import ttest").timeit()
                print 'part happy:', timeit.Timer('ttest.is_float_partition("12.2")', "import ttest").timeit()
    
        unittest.main()
    

    在我的机器上,输出为:

    fn sad: 0.220988988876
    fn happy: 0.212214946747
    .
    part sad: 1.2219619751
    part happy: 0.754667043686
    .
    re sad: 1.50515985489
    re happy: 1.01107215881
    .
    try sad: 2.40243887901
    try happy: 0.425730228424
    .
    ----------------------------------------------------------------------
    Ran 4 tests in 7.761s
    
    OK
    

    正如您所看到的,regex实际上并不像最初看起来那么糟糕,如果您真正需要速度,那么 fastnumbers 方法很好。

        6
  •  4
  •   Peter Moore    8 年前

    为了多样化,这里还有另一种方法。

    >>> all([i.isnumeric() for i in '1.2'.split('.',1)])
    True
    >>> all([i.isnumeric() for i in '2'.split('.',1)])
    True
    >>> all([i.isnumeric() for i in '2.f'.split('.',1)])
    False
    

    编辑:我确信它不会容纳所有的浮动情况,尤其是当有指数的时候。为了解决这个问题,它看起来是这样的。这将返回true only val是一个float,对于int则返回false,但其性能可能不如regex。

    >>> def isfloat(val):
    ...     return all([ [any([i.isnumeric(), i in ['.','e']]) for i in val],  len(val.split('.')) == 2] )
    ...
    >>> isfloat('1')
    False
    >>> isfloat('1.2')
    True
    >>> isfloat('1.2e3')
    True
    >>> isfloat('12e3')
    False
    
        7
  •  2
  •   John Gietzen    17 年前

    此regex将检查科学的浮点数:

    ^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$
    

    但是,我相信您最好的选择是在一次尝试中使用解析器。

        8
  •  2
  •   kodetojoy    10 年前

    如果您不需要担心数字的科学表达式或其他表达式,并且只使用可能是带句点或不带句点的数字的字符串:

    功能

    def is_float(s):
        result = False
        if s.count(".") == 1:
            if s.replace(".", "").isdigit():
                result = True
        return result
    

    拉姆达版本

    is_float = lambda x: x.replace('.','',1).isdigit() and "." in x
    

    例子

    if is_float(some_string):
        some_string = float(some_string)
    elif some_string.isdigit():
        some_string = int(some_string)
    else:
        print "Does not convert to int or float."
    

    这样就不会意外地将int转换成float。

        9
  •  1
  •   mathfac    7 年前

    我使用了前面提到的函数,但很快我注意到字符串“nan”、“inf”和它的变化被认为是数字。因此,我建议您改进该函数的版本,它将在这些类型的输入上返回false,并且不会失败“1E3”变体:

    def is_float(text):
        # check for nan/infinity etc.
        if text.isalpha():
            return False
        try:
            float(text)
            return True
        except ValueError:
            return False
    
        10
  •  1
  •   JayS    7 年前

    尝试转换为float。如果有错误,请打印ValueError异常。

    try:
        x = float('1.23')
        print('val=',x)
        y = float('abc')
        print('val=',y)
    except ValueError as err:
        print('floatErr;',err)
    

    输出:

    val= 1.23
    floatErr: could not convert string to float: 'abc'
    
        11
  •  0
  •   Lockey    8 年前

    我在寻找一些类似的代码,但看起来使用Try/Excepts是最好的方法。 这是我使用的代码。如果输入无效,它包含一个重试函数。我需要检查输入是否大于0,如果大于0,则将其转换为浮点。

    def cleanInput(question,retry=False): 
        inputValue = input("\n\nOnly positive numbers can be entered, please re-enter the value.\n\n{}".format(question)) if retry else input(question)
        try:
            if float(inputValue) <= 0 : raise ValueError()
            else : return(float(inputValue))
        except ValueError : return(cleanInput(question,retry=True))
    
    
    willbefloat = cleanInput("Give me the number: ")
    
        12
  •  0
  •   simhumileco Janarthanan Ramu    7 年前
    str(strval).isdigit()
    

    似乎很简单。

    处理以字符串、int或float形式存储的值

        13
  •  0
  •   simhumileco Janarthanan Ramu    7 年前

    函数的简化版本 is_digit(str) 在大多数情况下都足够(不考虑 指数记数法 “南” 价值):

    def is_digit(str):
        return str.lstrip('-').replace('.', '').isdigit()