检查字符串是否可以在 Python 中转换为浮点数[重复]

2024-12-18 08:38:00
admin
原创
132
摘要:问题描述:我有一些 Python 代码,可以遍历字符串列表并将它们转换为整数或浮点数(如果可能)。对于整数执行此操作非常简单if element.isdigit(): newelement = int(element) 浮点数比较难。现在我用它partition('.')来分割字符串,并检查以确保其中一边...

问题描述:

我有一些 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)

这可行,但显然 if 语句有点难以理解。我考虑的另一个解决方案是将转换包装在 try/catch 块中,然后查看它是否成功,如本问题所述。

有人有其他想法吗?关于分区和 try/catch 方法的相对优点有什么看法?


解决方案 1:

我只会用..

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

..很简单,而且有效。请注意,如果元素为 1<<1024,它仍会抛出 OverflowError。

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

import re
if re.match(r'^-?d+(?:.d+)$', element) is None:
    print("Not float")

解决方案 2:

Python3 检查浮点数的方法:

def is_float(element: any) -> bool:
    #If you expect None to be passed:
    if element is None: 
        return False
    try:
        float(element)
        return True
    except ValueError:
        return False

上面的 Python2 版本:如何将字符串解析为浮点数或整数?

一定要进行单元测试。什么是浮点数,什么不是浮点数,这些可能会让你感到惊讶:

Command to parse                        Is it a float?  Comment
--------------------------------------  --------------- ------------
print(isfloat(""))                      False
print(isfloat("1234567"))               True 
print(isfloat("1_2_3.4"))               True        123.4, underscores ignored
print(isfloat("NaN"))                   True        nan is also float
print(isfloat("123.456"))               True
print(isfloat("123.E4"))                True
print(isfloat(".1"))                    True
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("1,234"))                 False
print(isfloat("NULL"))                  False       case insensitive
print(isfloat("NaNananana BATMAN"))     False
print(isfloat(",1"))                    False           
print(isfloat("123.EE4"))               False           
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

像这样沉没异常是不对的,因为杀死金丝雀是不对的,因为浮点方法可能会因用户输入以外的原因而失败。不要在生命攸关的软件上使用这样的代码。此外,python 一直在改变其关于哪些 unicode 字符串可以提升为浮点的契约,因此预计此代码的这种行为会在主要版本更新时发生变化。

解决方案 3:

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

true仅当数字字符串中有一个或没有“。”时
才会返回。

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

将会回归false

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

将会回归false

解决方案 4:

总结

  • 如果您的输入主要是可以转换为浮点数的字符串,则该try: except:方法是最好的原生 Python 方法。

  • 如果您的输入主要是无法转换为浮点数的字符串,那么正则表达式或分区方法会更好。

  • 如果您 1) 不确定您的输入或需要更快的速度并且 2) 不介意并且可以安装第三方 C 扩展,那么fastnumbers会非常好用。


还有另一种方法可通过名为fastnumbers 的第三方模块获得(披露,我是作者);它提供了一个名为isfloat的函数。我采用了 Jacob Gabrielson 在此答案中概述的 unittest 示例,但添加了该fastnumbers.isfloat方法。我还应该注意,Jacob 的示例没有公正地对待正则表达式选项,因为该示例中的大部分时间都花在了全局查找上,这是因为点运算符……我修改了该函数以进行更公平的比较try: except:


def is_float_try(str):
    try:
        float(str)
        return True
    except ValueError:
        return False

import re
_float_regexp = re.compile(r"^[-+]?(?:[0-9]+(?:.[0-9]*)?|.[0-9]+)(?:[eE][-+]?[0-9]+)?$").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

正如您所见,正则表达式实际上并不像最初看起来那么糟糕,如果您真正需要速度,那么该fastnumbers方法相当不错。

解决方案 5:

如果您关心性能(我并不是建议您应该关心),那么基于 try 的方法显然是赢家(与基于分区的方法或正则表达式方法相比),只要您不期望出现大量无效字符串,在这种情况下它可能会更慢(大概是由于异常处理的成本)。

再次强调,我并不是建议你关心性能,只是在你每秒执行 100 亿次或类似操作的情况下提供数据。此外,基于分区的代码无法处理至少一个有效字符串。

$./floatstr.py
弗朗西斯·
分区悲伤:3.1102449894
分区快乐:2.09208488464
..
悲伤:7.76906108856
很高兴:7.09421992302
..
尝试悲伤:12.1525540352
尝试快乐:1.44165301323
。
=================================================== ===================
失败:test_partition(__main__.ConvertTests)
-------------------------------------------------- --------------------
回溯(最近一次调用最后一次):
  文件“./floatstr.py”,第 48 行,位于 test_partition
    self.failUnless(is_float_partition("20e2"))
断言错误

-------------------------------------------------- --------------------
耗时 33.670 秒,运行 8 次测试

失败(失败次数=1)

这里是代码(Python 2.6,正则表达式取自 John Gietzen 的答案):

def is_float_try(str):
    try:
        float(str)
        return True
    except ValueError:
        return False

import re
_float_regexp = re.compile(r"^[-+]?(?:[0-9]+(?:.[0-9]*)?|.[0-9]+)(?:[eE][-+]?[0-9]+)?$")
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\nrtition[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()

解决方案 6:

只是为了多样化,这里提供另一种方法。

>>> 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,只有 val 是浮点数,对于 int 则返回 False,但性能可能不如正则表达式。

>>> 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:

该函数的简化版本 is_digit(str),在大多数情况下都足够了(不考虑指数符号“NaN”值):

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

解决方案 8:

如果您不需要担心数字的科学或其他表达方式,而只处理带或不带句点的数字字符串:

功能

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

Lambda 版本

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:

该正则表达式将检查科学浮点数:

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

不过,我相信最好的选择是在尝试中使用解析器。

解决方案 10:

似乎许多正则表达式都会遗漏一些东西。到目前为止,这对我很有用:

(?i)^s*[+-]?(?:inf(inity)?|nan|(?:d+.?d*|.d+)(?:e[+-]?d+)?)s*$

它允许有符号的无穷大(或 inf)、nan、小数点前没有数字以及前导/尾随空格(如果需要)。需要^$以避免部分匹配类似 的1.2f-2内容1.2

如果您需要解析某些使用双精度科学计数法的文件,则可以使用[ed]而不是。您可能希望在之后替换它,或者在检查之前替换它们,因为该函数不允许这样做。e`D`float()

解决方案 11:

我使用了前面提到的函数,但很快我注意到字符串“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

解决方案 12:

您可以使用try--except子句else,这将捕获当传递的值无法转换为浮点数时引发的任何转换/值错误


  def try_parse_float(item):
      result = None
      try:
        float(item)
      except:
        pass
      else:
        result = float(item)
      return result

解决方案 13:

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

def cleanInput(question,retry=False): 
    inputValue = input("

Only positive numbers can be entered, please re-enter the value.

{}".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: ")

解决方案 14:

尝试转换为浮点数。如果出现错误,则打印 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'

解决方案 15:

将字典作为参数传递,它将转换可以转换为浮点数的字符串,并将其他字符串保留

def covertDict_float(data):
        for i in data:
            if data[i].split(".")[0].isdigit():
                try:
                    data[i] = float(data[i])
                except:
                    continue
        return data

解决方案 16:

我尝试了上述一些简单的选项,使用尝试测试转换为浮点数,发现大多数答复都存在问题。

简单测试(与上述答案类似):

entry = ttk.Entry(self, validate='key')
entry['validatecommand'] = (entry.register(_test_num), '%P')

def _test_num(P):
    try: 
        float(P)
        return True
    except ValueError:
        return False

问题出现在:

  • 输入‘-’来开始负数:

然后你又尝试,float('-')但失败了

  • 你输入了一个数字,但随后尝试删除所有数字

然后你又尝试,float('')但同样会失败

我的快速解决方案是:

def _test_num(P):
    if P == '' or P == '-': return True
    try: 
        float(P)
        return True
    except ValueError:
        return False

解决方案 17:

一个简单的函数,无需 try 和 except 操作即可获取数字类型

def number_type(number):
    if number.isdigit():
        return int(number)
    elif number.replace(".","").isdigit():
        return float(number)
    else:
        return(type(number))

解决方案 18:

我找到了一种可行的方法。需要验证这一点。第一次在这里放东西。

def isfloat(a_str):
    try:
        x=float(a_str)
        if x%1 == 0:
            return False
        elif x%1 != 0: #an else also do
            return True
    except Exception as error:
            return False

解决方案 19:

这很有魅力:

[dict([a,int(x) if isinstance(x, str)
 and x.isnumeric() else float(x) if isinstance(x, str)
 and x.replace('.', '', 1).isdigit() else x] for a, x in json_data.items())][0]

解决方案 20:

我编写了自己的函数。我没有使用 float(value),而是使用 floatN() 或 floatZ()。如果值不能转换为浮点数,则返回 None 或 0.0。我将它们保存在一个名为 safeCasts 的模块中。

def floatN(value):
    try:
        if value is not None:
            fvalue = float(value)
        else:
            fvalue = None
    except ValueError:
        fvalue = None

    return fvalue


def floatZ(value):
    try:
        if value is not None:
            fvalue = float(value)
        else:
            fvalue = 0.0
    except ValueError:
        fvalue = 0.0

    return fvalue

在其他模块中我导入它们

from safeCasts import floatN, floatZ

然后使用 floatN(value) 或 floatZ(value) 代替 float()。显然,您可以将此技术用于所需的任何强制转换函数。

解决方案 21:

这是一个简单但有趣的问题。下面提供的解决方案对我来说很有效:

import re

val = "25,000.93$"

regex = r"D"

splitted = re.split(regex, val)
splitted = list(filter(str.isdecimal, splitted))

if splitted:
    if len(splitted) > 1:
        splitted.insert(-1, ".")

    try:
        f = float("".join(splitted))
        print(f, "is float.")
        
    except ValueError:
        print("Not a float.")
        
else:
    print("Not a float.")

重要提示:此解决方案基于最后一个值splitted包含小数的假设。

解决方案 22:

您可以创建一个函数 isfloat(),并用它代替 isdigit() 来处理整数和浮点数,但不能像您期望的那样处理字符串。

a = raw_input('How much is 1 share in that company? 
')

def isfloat(num):
    try:
        float(num)
        return True
    except:
        return False
       
while not isfloat(a):
    print("You need to write a number!
")
    a = raw_input('How much is 1 share in that company? 
')

解决方案 23:

我们可以使用正则表达式:
`import re
if re.match('[0-9]*.?[0-9]+', <your_string>):
print("Its a float/int")
else:
print("Its something alien")`
让我用英语解释一下正则表达式,

    • -> 0 次或多次出现

    • -> 出现 1 次或多次

  • ? -> 0/1 发生

现在让我们转换

  • '[0-9]* -> 让 0-9 之间的数字出现 0 次或多次

  • \.? -> 后跟 0 或一个 '.'(如果您需要检查它是否可以是 int/float,否则我们也可以使用 ?,使用 {1})

  • [0-9]+ -> 后跟 0-9 之间的数字 0 次或多次

解决方案 24:

str(strval).isdigit()

看起来很简单。

处理以字符串、整数或浮点数存储的值

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用