如何检查一个字符串是否表示一个数字(浮点数或整数)?

1961

98
你现有的解决方案有什么问题吗?它很简短、快速且易读。 - Colonel Panic
5
你不仅仅可以返回True或False,你还可以适当修改返回的值。例如,你可以将非数字用引号括起来。 - Thruston
8
如果成功转换,返回float(s)的结果岂不更好?你仍然需要检查是否成功(结果为False),而且你已经完成了转换,这也是你可能想要的。 - Jiminion
10
尽管这个问题比较旧,但我想说这种方法被称为EAFP,是一种优雅的方式。因此,这可能是解决这种问题的最佳方案。 - thiruvenkadam
9
如果转换失败,不要返回float(s)的结果或None。如果你这样使用它x = float('0.00'); if x: use_float(x);,你的代码中现在有一个bug。这些函数抛出异常而不是一开始返回None的原因是为了避免Truthy值。更好的解决方案是在需要使用时避免实用程序函数,而是在调用float时使用try catch语句块捕获异常。 - ovangle
显示剩余16条评论
41个回答

1

这篇文章已经有很好的回答了。我想提供一种略微不同的观点。

我们可以进行字母的负面搜索,而不是寻找数字或浮点数。也就是说,我们可以让程序查找它是否不是字母。

## Check whether it is not alpha rather than checking if it is digit
print(not "-1.2345".isalpha())
print(not "-1.2345e-10".isalpha())

如果您确定字符串是格式良好的数字(如下面的条件1和条件2),它将有效地工作。但是,如果字符串不是一个格式良好的数字,那么它将失败。在这种情况下,它将返回一个数字匹配,即使该字符串不是一个有效的数字。为了处理这种情况,必须有许多基于规则的方法。然而,此时此刻,正则表达式浮现在我的脑海中。以下是三种情况。请注意,由于我不是正则表达式专家,因此正则表达式可能会更好。下面有两个列表:一个是有效数字,另一个是无效数字。必须选择有效数字,而无效数字则不得选取。
== 条件1:字符串保证是有效数字,但不包括'inf' ==
Valid_Numbers = ["1","-1","+1","0.0",".1","1.2345","-1.2345","+1.2345","1.2345e10","1.2345e-10","-1.2345e10","-1.2345E10","-inf"]
Invalid_Numbers = ["1.1.1","++1","--1","-1-1","1.23e10e5","--inf"]

################################ Condition 1: Valid number excludes 'inf' ####################################

Case_1_Positive_Result = list(map(lambda x: not x.isalpha(),Valid_Numbers))
print("The below must all be True")
print(Case_1_Positive_Result)

## This check assumes a valid number. So it fails for the negative cases and wrongly detects string as number
Case_1_Negative_Result = list(map(lambda x: not x.isalpha(),Invalid_Numbers))
print("The below must all be False")
print(Case_1_Negative_Result)

The below must all be True
[True, True, True, True, True, True, True, True, True, True, True, True, True]
The below must all be False
[True, True, True, True, True, True]

== 条件2: 字符串保证是一个有效的数字,且选取 'inf' ==

################################ Condition 2: Valid number includes 'inf'  ###################################
Case_2_Positive_Result = list(map(lambda x: x=="inf" or not x.isalpha(),Valid_Numbers+["inf"]))
print("The below must all be True")
print(Case_2_Positive_Result)

## This check assumes a valid number. So it fails for the negative cases and wrongly detects string as number
Case_2_Negative_Result = list(map(lambda x: x=="inf" or not x.isalpha(),Invalid_Numbers+["++inf"]))
print("The below must all be False")
print(Case_2_Negative_Result)

The below must all be True
[True, True, True, True, True, True, True, True, True, True, True, True, True, True]
The below must all be False
[True, True, True, True, True, True, True]

== 条件3:字符串不保证是有效的数字 ==

import re
CompiledPattern = re.compile(r"([+-]?(inf){1}$)|([+-]?[0-9]*\.?[0-9]*$)|([+-]?[0-9]*\.?[0-9]*[eE]{1}[+-]?[0-9]*$)")
Case_3_Positive_Result = list(map(lambda x: True if CompiledPattern.match(x) else False,Valid_Numbers+["inf"]))
print("The below must all be True")
print(Case_3_Positive_Result)

## This check assumes a valid number. So it fails for the negative cases and wrongly detects string as number
Case_3_Negative_Result = list(map(lambda x: True if CompiledPattern.match(x) else False,Invalid_Numbers+["++inf"]))
print("The below must all be False")
print(Case_3_Negative_Result)

The below must all be True
[True, True, True, True, True, True, True, True, True, True, True, True, True, True]
The below must all be False
[False, False, False, False, False, False, False]

1
这是我简单的做法。假设我正在循环一些字符串,如果它们最终被证明是数字,我想将它们添加到一个数组中。
try:
    myvar.append( float(string_to_check) )
except:
    continue

如果字符串是数字,将myvar.apppend替换为您想要执行的任何操作。思路是尝试使用float()操作,并使用返回的错误来确定字符串是否为数字。


你应该将该函数的附加部分移动到else语句中,以避免在数组出现问题时意外触发异常。 - DarwinSurvivor

1
用户辅助函数:

def if_ok(fn, string):
  try:
    return fn(string)
  except Exception as e:
    return None

然后。
if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str)
is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])

看起来很有趣,但请解释一下你的解决方案以及如何使用它,附上一些输入和输出。 - not2qubit

0

试试这个。

 def is_number(var):
    try:
       if var == int(var):
            return True
    except Exception:
        return False

无法响应is_number('10') - geotheory
@geotheory,你说的“无响应”是什么意思? - Solomon Ucko

0

抱歉发了这个僵尸线程的帖子 - 只是想让代码更完整...

# is_number() function - Uses re = regex library
# Should handle all normal and complex numbers
# Does not accept trailing spaces. 
# Note: accepts both engineering "j" and math "i" but only the imaginary part "+bi" of a complex number a+bi
# Also accepts inf or NaN
# Thanks to the earlier responders for most the regex fu

import re

ISNUM_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?[ij]?$')

def is_number(str):
#change order if you have a lot of NaN or inf to parse
    if ISNUM_REGEXP.match(str) or str == "NaN" or str == "inf": 
        return True 
    else:
        return False
# A couple test numbers
# +42.42e-42j
# -42.42E+42i

print('Is it a number?', is_number(input('Gimme any number: ')))

给我一个数字:+42.42e-42j

它是一个数字吗?是的


0

我的简短回答是: 可能会有重复的部分,对此我很抱歉。 ... def is_float(s): if s.isdigit(): return False try: float(s) return True except Exception as e: return False


0

你可以通过返回比True和False更有用的值来推广异常处理技术。例如,这个函数会在字符串周围加上引号,但不会对数字进行操作。这正是我需要的一个快速而简单的过滤器,以便为R创建一些变量定义。

import sys

def fix_quotes(s):
    try:
        float(s)
        return s
    except ValueError:
        return '"{0}"'.format(s)

for line in sys.stdin:
    input = line.split()
    print input[0], '<- c(', ','.join(fix_quotes(c) for c in input[1:]), ')'

0

对于我非常简单且非常常见的用例:这个由键盘输入的字符串是否为数字

我阅读了大多数答案,最终得出:

def isNumeric(string):
    result = True
    try:
        x = float(string)
       result = (x == x) and (x - 1 != x)
    except ValueError:
        result = False
    return result

对于(+-)NaN(+-)inf,它将返回False。

您可以在此处查看:https://trinket.io/python/ce32c0e54e


0
def is_number(x:str):
    x = x.replace(".", "", 1)
    if x.startswith("-"):
        x = x[1:]
    return x.isdigit()

if __name__ == '__main__':
    for si in ["123.456", "-123.456", "123", "-123", "--123", "a123", "123a"]:
        print(si, is_number(si))

-2

我有一个类似的问题。我想要将一组字符串转换为浮点数,而不是定义一个isNumber函数,高级术语来说就是:

[ float(s) for s in list if isFloat(s)]

我们无法真正将float(s)和isFloat(s)函数分开:这两个结果应该由同一个函数返回。

此外,如果float(s)失败,整个过程将失败,而不仅仅是忽略错误的元素。此外,“0”是一个有效的数字,应该包含在列表中。在筛选错误元素时,请务必不要排除0

因此,上述理解必须进行某种修改:

  • 如果列表中的任何元素无法转换,请忽略它并不抛出异常
  • 避免为每个元素调用float(s)超过一次(一次用于转换,另一次用于测试)
  • 如果转换后的值为0,则应仍在最终列表中存在

我提出了受C#可为空数值类型启发的解决方案。这些类型由结构体表示,其中包含数值和一个布尔值,指示该值是否有效:

def tryParseFloat(s):
    try:
        return(float(s), True)
    except:
        return(None, False)

tupleList = [tryParseFloat(x) for x in list]
floats = [v for v,b in tupleList if b]

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