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

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个回答

5

我需要确定一个字符串是否可以转换为基本类型(float,int,str,bool)。在网上没有找到任何相关的信息后,我创建了以下代码:

def str_to_type (s):
    """ Get possible cast type for a string

    Parameters
    ----------
    s : string

    Returns
    -------
    float,int,str,bool : type
        Depending on what it can be cast to

    """    
    try:                
        f = float(s)        
        if "." not in s:
            return int
        return float
    except ValueError:
        value = s.upper()
        if value == "TRUE" or value == "FALSE":
            return bool
        return type(s)

示例

str_to_type("true") # bool
str_to_type("6.0") # float
str_to_type("6") # int
str_to_type("6abc") # str
str_to_type(u"6abc") # unicode       

您可以捕获数据类型并使用它。
s = "6.0"
type_ = str_to_type(s) # float
f = type_(s) 

回答不错,但不是完全通用的:str_to_type("123e-4") 返回 int,而 float("123e-4") 返回 0.0123。此外,str_to_type("NaN") 返回 int - joanis
if "." not in s: 更改为 if "." not in s and "e" not in s and "N" not in s: 可以解决我在这里展示的情况,但它会使代码变得笨重,而且我不确定它是否能捕获所有情况。 - joanis
我的首选解决方案,也是更安全的一种,是使用嵌套的try/except语句:将i = int(s); return int包装在第一个try/except中,然后将f = float(s); return float放在第二个try/except中,并将其全部放在第一个try/except的except块中。就像user1508746的答案的结构一样,只是返回值不同。 - joanis

4

我进行了一些速度测试。假设如果字符串可能是数字,则try/except策略是最快的。如果字符串不太可能是数字并且您有兴趣进行整数检查,值得进行一些测试(isdigit加上前导' - ')。如果您想要检查浮点数,则必须使用try/except代码而不带转义符。


3

RyanN建议:

如果你想针对NaN和Inf返回False,可以将代码修改为 x = float(s); return (x == x) and (x - 1 != x)。这个方法应该会对除了Inf和NaN之外的所有浮点数返回True。

但是这并不完全奏效,因为对于足够大的浮点数,x-1 == x 会返回true。例如,2.0**54 - 1 == 2.0**54


3

我在解决一个问题时遇到了这个帖子,即如何以最直观的方式将一组数据转换为字符串和数字。阅读原始代码后,我意识到我需要两种不同的方法:

1- 如果字符串表示整数,则我需要一个整数结果

2- 我需要一个数字或字符串结果来插入数据结构中

因此,我修改了原始代码以生成这个衍生版本:

def string_or_number(s):
    try:
        z = int(s)
        return z
    except ValueError:
        try:
            z = float(s)
            return z
        except ValueError:
            return s

2
import re
def is_number(num):
    pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')
    result = pattern.match(num)
    if result:
        return True
    else:
        return False


​>>>: is_number('1')
True

>>>: is_number('111')
True

>>>: is_number('11.1')
True

>>>: is_number('-11.1')
True

>>>: is_number('inf')
False

>>>: is_number('-inf')
False

2
你不认为 1e6 代表一个数字吗? - Mark Dickinson

2

这段代码处理指数、浮点数和整数,而不使用正则表达式。

return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False

如果遇到字符串,则出现错误。 - ZygD

1

我也使用了你提到的函数,但很快我注意到"Nan"、"Inf"及其变体被视为数字。因此,我建议你改进函数的版本,对这些类型的输入返回false,并且不会失败于"1e3"等变体:

def is_float(text):
    try:
        float(text)
        # check for nan/infinity etc.
        if text.isalpha():
            return False
        return True
    except ValueError:
        return False

1

一种快速简单的选项是检查数据类型:

def is_number(value):
    return type(value) in [int, float]

或者,如果您想测试字符串的值是否为数字:

def isNumber (value):
    return True if type(value) in [int, float] else str(value).replace('.','',1).isdigit()

测试:

>>> isNumber(1)
True

>>> isNumber(1/3)
True

>>> isNumber(1.3)
True

>>> isNumber('1.3')
True

>>> isNumber('s1.3')
False

指数的话,用 e 吧? - john k
是的,@johnktejik 这可能会成为一个问题。这个函数会将像'1.54-e8'和'0X45'这样的字符串返回false。对于这种类型的数字,您可以使用正则表达式来解决这个问题。 - Rafael Braga

1
def is_float(s):
    if s is None:
        return False

    if len(s) == 0:
        return False

    digits_count = 0
    dots_count = 0
    signs_count = 0

    for c in s:
        if '0' <= c <= '9':
            digits_count += 1
        elif c == '.':
            dots_count += 1
        elif c == '-' or c == '+':
            signs_count += 1
        else:
            return False

    if digits_count == 0:
        return False

    if dots_count > 1:
        return False

    if signs_count > 1:
        return False

    return True

1

我知道我来晚了,但是想出了一个这里没有的解决方案: 这个解决方案遵循Python中的EAFP原则

def get_number_from_string(value):
    try:
        int_value = int(value)
        return int_value

    except ValueError:
        return float(value)

解释:

如果字符串中的值是一个 float,而我首先尝试将其解析为一个 int,它会抛出一个 ValueError。因此,我捕获该错误并将该值解析为 float 并返回。


如果value是像"1.f"这样的字符串,那么在except块中会再次失败,对吧? - sinekonata
@sinekonata,问题假设数字以字符串形式存在。 - Gru

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