如何将字符串解析为float或int?

2024-04-26 20:42:28 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中,如何将像"545.2222"这样的数字字符串解析为对应的浮点值545.2222?或者将字符串"31"解析为整数31

我只想知道如何将floatstr解析为float,以及(分别)将intstr解析为int


Tags: 字符串数字整数floatint浮点intstrfloatstr
25条回答

这是一个将任何object(不仅仅是str)转换为intfloat的函数,基于提供的实际字符串是否看起来像intfloat。此外,如果它是同时具有__float__int__方法的对象,则默认使用__float__

def conv_to_num(x, num_type='asis'):
    '''Converts an object to a number if possible.
    num_type: int, float, 'asis'
    Defaults to floating point in case of ambiguity.
    '''
    import numbers

    is_num, is_str, is_other = [False]*3

    if isinstance(x, numbers.Number):
        is_num = True
    elif isinstance(x, str):
        is_str = True

    is_other = not any([is_num, is_str])

    if is_num:
        res = x
    elif is_str:
        is_float, is_int, is_char = [False]*3
        try:
            res = float(x)
            if '.' in x:
                is_float = True
            else:
                is_int = True
        except ValueError:
            res = x
            is_char = True

    else:
        if num_type == 'asis':
            funcs = [int, float]
        else:
            funcs = [num_type]

        for func in funcs:
            try:
                res = func(x)
                break
            except TypeError:
                continue
        else:
            res = x
float(x) if '.' in x else int(x)

将字符串传递给此函数:

def string_to_number(str):
  if("." in str):
    try:
      res = float(str)
    except:
      res = str  
  elif(str.isdigit()):
    res = int(str)
  else:
    res = str
  return(res)

它将根据传递的内容返回int、float或string。

是int的字符串

print(type(string_to_number("124")))
<class 'int'>

浮点字符串

print(type(string_to_number("12.4")))
<class 'float'>

字符串,即字符串

print(type(string_to_number("hello")))
<class 'str'>

看起来像浮点数的字符串

print(type(string_to_number("hel.lo")))
<class 'str'>
def get_int_or_float(v):
    number_as_float = float(v)
    number_as_int = int(number_as_float)
    return number_as_int if number_as_float == number_as_int else number_as_float
def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)

检查字符串是否为浮点数的Python方法:

def is_float(value):
  try:
    float(value)
    return True
  except:
    return False

此函数的更长和更准确的名称可以是:is_convertible_to_float(value)

什么是,什么不是Python中的浮点数可能会让您吃惊:

val                   is_float(val) Note
--------------------  ----------   --------------------------------
""                    False        Blank string
"127"                 True         Passed string
True                  True         Pure sweet Truth
"True"                False        Vile contemptible lie
False                 True         So false it becomes true
"123.456"             True         Decimal
"      -127    "      True         Spaces trimmed
"\t\n12\r\n"          True         whitespace ignored
"NaN"                 True         Not a number
"NaNanananaBATMAN"    False        I am Batman
"-iNF"                True         Negative infinity
"123.E4"              True         Exponential notation
".1"                  True         mantissa only
"1,234"               False        Commas gtfo
u'\x30'               True         Unicode is fine.
"NULL"                False        Null is not special
0x3fade               True         Hexadecimal
"6e7777777777777"     True         Shrunk to infinity
"1.797693e+308"       True         This is max value
"infinity"            True         Same as inf
"infinityandBEYOND"   False        Extra characters wreck it
"12.34.56"            False        Only one dot allowed
u'四'                 False        Japanese '4' is not a float.
"#56"                 False        Pound sign
"56%"                 False        Percent of what?
"0E0"                 True         Exponential, move dot 0 places
0**0                  True         0___0  Exponentiation
"-5e-5"               True         Raise to a negative number
"+1e1"                True         Plus is OK with exponent
"+1e1^5"              False        Fancy exponent not interpreted
"+1e1.3"              False        No decimals in exponent
"-+1"                 False        Make up your mind
"(1)"                 False        Parenthesis is bad

你以为你知道数字是多少?你没有你想的那么好!没什么好惊讶的。

不要在生命关键型软件上使用此代码!

通过这种方式捕获广泛的异常,杀死金丝雀并吞食异常会创建一个很小的机会,使有效的float as string返回false。代码的float(...)行可能由于与字符串内容无关的一千个原因中的任何一个而失败。但是如果你用像Python这样的duck-typing原型语言编写生命关键型软件,那么你会遇到更大的问题。

使用:

def num(s):
    try:
        for each in s:
            yield int(each)
    except ValueError:
        yield float(each)
a = num(["123.55","345","44"])
print a.next()
print a.next()

这是我能想到的最像Python的方法。

如果您不反对第三方模块,可以签出fastnumbers模块。它提供了一个名为fast_real的函数,该函数完全按照问题的要求执行,并且比纯Python实现更快:

>>> from fastnumbers import fast_real
>>> fast_real("545.2222")
545.2222
>>> type(fast_real("545.2222"))
float
>>> fast_real("31")
31
>>> type(fast_real("31"))
int

本地化和逗号

对于引发异常的float("545,545.2222")等情况,应该考虑在数字的字符串表示形式中使用逗号的可能性。相反,请使用locale中的方法将字符串转换为数字并正确解释逗号。一旦为所需的数字约定设置了区域设置,locale.atof方法一步就转换为浮点。

示例1——美国数字惯例

在美国和英国,逗号可以用作千位分隔符。在这个使用美式语言环境的示例中,逗号被正确地作为分隔符处理:

>>> import locale
>>> a = u'545,545.2222'
>>> locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
'en_US.UTF-8'
>>> locale.atof(a)
545545.2222
>>> int(locale.atof(a))
545545
>>>

示例2——欧洲数字惯例

majority of countries of the world中,逗号用于小数点而不是句点。在这个使用法语语言环境的示例中,逗号被正确地处理为十进制标记:

>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222

方法locale.atoi也可用,但参数应为整数。

YAML解析器可以帮助您找出字符串的数据类型。使用yaml.load(),然后可以使用type(result)测试类型:

>>> import yaml

>>> a = "545.2222"
>>> result = yaml.load(a)
>>> result
545.22220000000004
>>> type(result)
<type 'float'>

>>> b = "31"
>>> result = yaml.load(b)
>>> result
31
>>> type(result)
<type 'int'>

>>> c = "HI"
>>> result = yaml.load(c)
>>> result
'HI'
>>> type(result)
<type 'str'>

处理十六进制、八进制、二进制、十进制和浮点

这个解决方案将处理数字的所有字符串约定(我所知道的)。

def to_number(n):
    ''' Convert any number representation to a number 
    This covers: float, decimal, hex, and octal numbers.
    '''

    try:
        return int(str(n), 0)
    except:
        try:
            # python 3 doesn't accept "010" as a valid octal.  You must use the
            # '0o' prefix
            return int('0o' + n, 0)
        except:
            return float(n)

这个测试用例输出说明了我在说什么。

======================== CAPTURED OUTPUT =========================
to_number(3735928559)   = 3735928559 == 3735928559
to_number("0xFEEDFACE") = 4277009102 == 4277009102
to_number("0x0")        =          0 ==          0
to_number(100)          =        100 ==        100
to_number("42")         =         42 ==         42
to_number(8)            =          8 ==          8
to_number("0o20")       =         16 ==         16
to_number("020")        =         16 ==         16
to_number(3.14)         =       3.14 ==       3.14
to_number("2.72")       =       2.72 ==       2.72
to_number("1e3")        =     1000.0 ==       1000
to_number(0.001)        =      0.001 ==      0.001
to_number("0xA")        =         10 ==         10
to_number("012")        =         10 ==         10
to_number("0o12")       =         10 ==         10
to_number("0b01010")    =         10 ==         10
to_number("10")         =         10 ==         10
to_number("10.0")       =       10.0 ==         10
to_number("1e1")        =       10.0 ==         10

下面是测试:

class test_to_number(unittest.TestCase):

    def test_hex(self):
        # All of the following should be converted to an integer
        #
        values = [

                 #          HEX
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (0xDEADBEEF  , 3735928559), # Hex
                ("0xFEEDFACE", 4277009102), # Hex
                ("0x0"       ,          0), # Hex

                 #        Decimals
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (100         ,        100), # Decimal
                ("42"        ,         42), # Decimal
            ]



        values += [
                 #        Octals
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (0o10        ,          8), # Octal
                ("0o20"      ,         16), # Octal
                ("020"       ,         16), # Octal
            ]


        values += [
                 #        Floats
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (3.14        ,       3.14), # Float
                ("2.72"      ,       2.72), # Float
                ("1e3"       ,       1000), # Float
                (1e-3        ,      0.001), # Float
            ]

        values += [
                 #        All ints
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                ("0xA"       ,         10), 
                ("012"       ,         10), 
                ("0o12"      ,         10), 
                ("0b01010"   ,         10), 
                ("10"        ,         10), 
                ("10.0"      ,         10), 
                ("1e1"       ,         10), 
            ]

        for _input, expected in values:
            value = to_number(_input)

            if isinstance(_input, str):
                cmd = 'to_number("{}")'.format(_input)
            else:
                cmd = 'to_number({})'.format(_input)

            print("{:23} = {:10} == {:10}".format(cmd, value, expected))
            self.assertEqual(value, expected)

这是的更正版本 https://stackoverflow.com/a/33017514/5973334

这将尝试分析字符串并返回intfloat,具体取决于字符串所表示的内容。 它可能会引发解析异常或have some unexpected behaviour

  def get_int_or_float(v):
        number_as_float = float(v)
        number_as_int = int(number_as_float)
        return number_as_int if number_as_float == number_as_int else 
        number_as_float

float("545.2222")int(float("545.2222"))

这是对你问题的另一种解释(提示:它很模糊)。你可能在找这样的东西:

def parseIntOrFloat( aString ):
    return eval( aString )

它是这样工作的。。。

>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545

理论上,存在注入漏洞。字符串可以是"import os; os.abort()"。然而,在没有任何背景资料的情况下,这种可能性只是理论上的推测。因为问题很模糊,所以根本不清楚这个漏洞是否真的存在。

我很惊讶没有人提到regex,因为有时字符串在转换为数字之前必须准备好并规范化

import re
def parseNumber(value, as_int=False):
    try:
        number = float(re.sub('[^.\-\d]', '', value))
        if as_int:
            return int(number + 0.5)
        else:
            return number
    except ValueError:
        return float('nan')  # or None if you wish

用法:

parseNumber('13,345')
> 13345.0

parseNumber('- 123 000')
> -123000.0

parseNumber('99999\n')
> 99999.0

顺便说一句,有件事可以证明你有一个号码:

import numbers
def is_number(value):
    return isinstance(value, numbers.Number)
    # will work with int, float, long, Decimal
def num(s):
    """num(s)
    num(3),num(3.7)-->3
    num('3')-->3, num('3.7')-->3.7
    num('3,700')-->ValueError
    num('3a'),num('a3'),-->ValueError
    num('3e4') --> 30000.0
    """
    try:
        return int(s)
    except ValueError:
        try:
            return float(s)
        except ValueError:
            raise ValueError('argument is not a string of number')

使用:

>>> str_float = "545.2222"
>>> float(str_float)
545.2222
>>> type(_) # Check its type
<type 'float'>

>>> str_int = "31"
>>> int(str_int)
31
>>> type(_) # Check its type
<type 'int'>

要在python中进行类型转换,请使用该类型的构造函数函数,并将字符串(或尝试转换的任何值)作为参数传递。

例如:

>>>float("23.333")
   23.333

在幕后,python正在调用objects__float__方法,该方法应该返回参数的浮点表示。这尤其强大,因为您可以使用__float__方法定义自己的类型(使用类),以便可以使用float(myobject)将其转换为float。

这个问题似乎有点老了。但是我建议使用一个parseStr函数,它可以产生类似的结果,也就是说,返回整数或浮点数,如果给定的ASCII字符串不能转换成任何一个,则返回原样。当然,代码可能会调整为只执行您想要的操作:

   >>> import string
   >>> parseStr = lambda x: x.isalpha() and x or x.isdigit() and \
   ...                      int(x) or x.isalnum() and x or \
   ...                      len(set(string.punctuation).intersection(x)) == 1 and \
   ...                      x.count('.') == 1 and float(x) or x
   >>> parseStr('123')
   123
   >>> parseStr('123.3')
   123.3
   >>> parseStr('3HC1')
   '3HC1'
   >>> parseStr('12.e5')
   1200000.0
   >>> parseStr('12$5')
   '12$5'
   >>> parseStr('12.2.2')
   '12.2.2'

用户代码逻辑哈雷是正确的,但请记住,如果知道字符串是整数(例如545),则可以调用int(“545”),而无需首先转换为浮点。

如果字符串在列表中,也可以使用map函数。

>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>

只有它们都是同一类型的才好。

>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545

我用这个函数

import ast

def parse_str(s):
   try:
      return ast.literal_eval(str(s))
   except:
      return

它将把字符串转换为它的类型

value = parse_str('1')  # Returns Integer
value = parse_str('1.5')  # Returns Float

这是另一个值得一提的方法,ast.literal_eval

This can be used for safely evaluating strings containing Python expressions from untrusted sources without the need to parse the values oneself.

也就是说,一个安全的“评估”

>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31

In Python, how can I parse a numeric string like "545.2222" to its corresponding float value, 542.2222? Or parse the string "31" to an integer, 31? I just want to know how to parse a float string to a float, and (separately) an int string to an int.

你要求分开做这些很好。如果你把它们混在一起,你可能是在为以后的问题做准备。简单的答案是:

"545.2222"浮动:

>>> float("545.2222")
545.2222

"31"为整数:

>>> int("31")
31

其他字符串和文字之间的转换、Int:

从不同的基数转换,你应该提前知道基数(默认为10)。注意,您可以在它们前面加上Python对其文本的期望值(见下文)或删除前缀:

>>> int("0b11111", 2)
31
>>> int("11111", 2)
31
>>> int('0o37', 8)
31
>>> int('37', 8)
31
>>> int('0x1f', 16)
31
>>> int('1f', 16)
31

如果您事先不知道基址,但您知道它们将具有正确的前缀,那么如果您将0作为基址,Python可以为您推断:

>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31

其他基数的非十进制(即整数)文字

但是,如果您的动机是让自己的代码清楚地表示硬编码的特定值,那么您可能不需要从基转换-您可以让Python使用正确的语法自动为您进行转换。

您可以使用apropos前缀自动转换为带the following literals的整数。这些对Python 2和Python 3有效:

二进制,前缀0b

>>> 0b11111
31

八进制,前缀0o

>>> 0o37
31

十六进制,前缀0x

>>> 0x1f
31

这在描述二进制标志、代码中的文件权限或颜色的十六进制值时非常有用—例如,请注意不要使用引号:

>>> 0b10101 # binary flags
21
>>> 0o755 # read, write, execute perms for owner, read & ex for group & others
493
>>> 0xffffff # the color, white, max values for red, green, and blue
16777215

使不明确的Python 2八进制与Python 3兼容

如果在Python 2中看到以0开头的整数,则这是(不推荐使用)八进制语法。

>>> 037
31

它很糟糕,因为它看起来应该是37。所以在Python 3中,它现在引发了一个SyntaxError

>>> 037
  File "<stdin>", line 1
    037
      ^
SyntaxError: invalid token

将Python的2个八进制转换为在2和3中都可以使用0o前缀的八进制:

>>> 0o37
31

您需要考虑舍入才能正确执行此操作。

即int(5.1)=>;5 int(5.6)=>;5——错误,应该是6,所以我们做int(5.6+0.5)=>;6

def convert(n):
    try:
        return int(n)
    except ValueError:
        return float(n + 0.5)

相关问题 更多 >