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

Tri*_*ick 2108 python floating-point parsing integer type-conversion

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

我只是想知道如何将一个浮点数 解析str为a float,并且(单独)将一个int 解析str为一个int.

Har*_*mbe 2473

>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
Run Code Online (Sandbox Code Playgroud)

  • @MangatRaiModi浮点数本身就不完美,表示小数.有关更多信息,请参阅/sf/ask/1532702951/ (47认同)
  • `int(a)`会给出一个错误,即字符串不是一个有效的整数:`ValueError:int(无效的文字),带有基数10:'545.222',但是从浮点数转换为int是支持的转换. (22认同)
  • 为什么不简单地`int(a)`但是`int(float(a))`? (17认同)
  • 只是想知道为什么到底有'04'?为什么不简单'00'?我目前的python版本没有'04'. (7认同)
  • 如果你想要安全,你应该处理`ValueError` (3认同)
  • @MangatRaiModi python 不久前更改了浮点数的舍入策略,它曾经使用固定位数,现在它使用“最短往返”表示。 (2认同)

Jav*_*ier 492

def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)
Run Code Online (Sandbox Code Playgroud)

  • *隐式*混合浮点数/整数可能会导致细微的错误,因为使用浮点数可能会导致精度损失,或浮点数/整数的"/"运算符可能导致不同的结果.根据上下文,最好返回int或float,而不是两者. (80认同)
  • @JFSebastian你是完全正确的,但有时你希望输入决定它将是哪一个.让输入决定哪一个可以很好地使用鸭子打字. (14认同)
  • 当它不能转换为float时,你可以嵌套另一个`try`来抛出异常. (4认同)
  • 以 `s = u'\u0000'` 失败 (2认同)

Eri*_*ski 481

用于检查字符串是否为float的Python方法:

def is_float(value):
  try:
    float(value)
    return True
  except:
    return False
Run Code Online (Sandbox Code Playgroud)

此功能的更长,更准确的名称可能是: 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
Run Code Online (Sandbox Code Playgroud)

你认为你知道什么数字?你没有想象的那么好!不是很大的惊喜.

  • 该 except 子句应限制为“TypeError, ValueError” (5认同)
  • 我在2014年发布了这个答案。多年来,中文4的“ UTF-8”字形一直在变化,具体取决于stackoverflow开发人员如何在其Microsoft工具栈上更改其字符编码方案。多年来,随着新的转换方案断言其新的意识形态,看到它的失败是一种好奇。但是,是的,任何东方东方数字的“ UTF-8”字形都不是Python浮点数。巴津加。 (3认同)
  • 在如此广泛的例外情况下,怎么能这样反对呢? (3认同)

wim*_*wim 122

这是另一种值得在此提及的方法,ast.literal_eval:

这可以用于安全地评估包含来自不可信来源的Python表达式的字符串,而无需自己解析值.

也就是说,安全'评估'

>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
Run Code Online (Sandbox Code Playgroud)

  • 这不是*解决问题的好方法.它在Python 2中运行良好,但在Python 3中发生以下情况:```python >>> import ast >>> ast.literal_eval('1-800-555-1212') - 2566 >>>```To澄清为什么这是一个问题,如果你想让它单独留下电话号码而不是假设它们是数学表达式,那么这种方法不适合你. (9认同)
  • @royce3 根据记录,在 Python 3 中,`ast` 不会再将电话号码直接评估为 -2566。它位于 Python 3.7 [变更日志](https://docs.python.org/3/whatsnew/3.7.html #changes-in-the-python-api): _`ast.literal_eval()` 现在更加严格。不再允许任意数字的加法和减法。(由 Serhiy Storchaka 在 [bpo-31778](https://github.com/python/cpython/issues/75959) 中贡献)_ (5认同)
  • @ royce3是的,这是一个好点,用户应该提防.最初修改了该行为是为了解决复杂文字解析的一些问题.它可以说是'ast.literal_eval`中的一个错误,已在[此处](/sf/ask/1452374171/)进行了讨论. (4认同)

小智 76

float(x) if '.' in x else int(x)
Run Code Online (Sandbox Code Playgroud)

  • @Emile:我不会称"2e-3"为"极端情况".这个答案刚刚打破. (125认同)
  • Nitpick:不适用于像浮子这样的极端情况("2e-3") (63认同)
  • 注意:处理作为字符串传递的金额时要小心,因为有些国家使用","作为小数分隔符 (21认同)
  • @BenG不要把钱当作浮动来操纵.那是在惹麻烦.用十进制钱!(但你对','的评论仍然有效且重要) (14认同)
  • 不要忘记"非数字"(NaN)和+/-无穷大也是有效的浮点值.所以`float("nan")`是一个完全有效的浮点值,上面的答案根本就没有 (4认同)
  • 很容易被 IP 地址破解 - `192.168.0.1`;或`"这不是一个好方法。:)"` (4认同)

Mar*_*ian 63

本地化和逗号

您应该考虑数字的字符串表示形式中逗号的可能性,例如 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
>>>
Run Code Online (Sandbox Code Playgroud)

示例2 - 欧洲数字惯例

在世界上大多数国家/地区,逗号用于十进制标记而不是句点.在此示例中,使用法语区域设置,逗号可以正确处理为小数点:

>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222
Run Code Online (Sandbox Code Playgroud)

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


Set*_*ton 25

如果您不反对第三方模块,可以查看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
Run Code Online (Sandbox Code Playgroud)


小智 24

用户codelogicharley是正确的,但请记住,如果你知道字符串是一个整数(例如,545),你可以调用int("545")而不首先转换为float.

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

>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>
Run Code Online (Sandbox Code Playgroud)

如果他们都是同一类型,那就好了.


krz*_*zym 19

这个问题似乎有点老了.但是,让我建议一个函数,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'
Run Code Online (Sandbox Code Playgroud)

  • `1e3`是python中的一个数字,但是根据你的代码是一个字符串. (7认同)

Aar*_*all 19

在Python中,如何将像"545.2222"这样的数字字符串解析为相应的浮点值542.2222?或者将字符串"31"解析为整数,31? 我只想知道如何将浮点字符串解析为float,并(单独)将int字符串解析为int.

你要求分别做这些是很好的.如果你正在混合它们,你可能会在以后为自己设置问题.简单的答案是:

"545.2222" 漂浮:

>>> float("545.2222")
545.2222
Run Code Online (Sandbox Code Playgroud)

"31" 到整数:

>>> int("31")
31
Run Code Online (Sandbox Code Playgroud)

其他转换,来自字符串和文字的内容:

各种基础的转换,你应该事先知道基数(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
Run Code Online (Sandbox Code Playgroud)

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

>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31
Run Code Online (Sandbox Code Playgroud)

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

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

您可以使用apropos前缀自动转换为具有以下文字的整数.这些对Python 2和3有效:

二进制,前缀 0b

>>> 0b11111
31
Run Code Online (Sandbox Code Playgroud)

八进制,前缀 0o

>>> 0o37
31
Run Code Online (Sandbox Code Playgroud)

十六进制,前缀 0x

>>> 0x1f
31
Run Code Online (Sandbox Code Playgroud)

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

>>> 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
Run Code Online (Sandbox Code Playgroud)

制作模糊的Python 2 octals与Python 3兼容

如果你看到一个以0开头的整数,在Python 2中,这是(不推荐的)八进制语法.

>>> 037
31
Run Code Online (Sandbox Code Playgroud)

这很糟糕,因为它看起来应该是值37.所以在Python 3中,它现在提出了一个SyntaxError:

>>> 037
  File "<stdin>", line 1
    037
      ^
SyntaxError: invalid token
Run Code Online (Sandbox Code Playgroud)

将您的Python 2八进制转换为在2和3中均使用0o前缀的八进制:

>>> 0o37
31
Run Code Online (Sandbox Code Playgroud)


cod*_*gic 16

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


Raf*_*afe 13

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'>
Run Code Online (Sandbox Code Playgroud)


Sha*_*eem 13

我使用这个功能

import ast

def parse_str(s):
   try:
      return ast.literal_eval(str(s))
   except:
      return
Run Code Online (Sandbox Code Playgroud)

它会将字符串转换为其类型

value = parse_str('1')  # Returns Integer
value = parse_str('1.5')  # Returns Float
Run Code Online (Sandbox Code Playgroud)

  • 请注意,“parse_str('1')”(带空格)将返回“None”,而不是“1”。 (2认同)

Tot*_*oro 11

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
Run Code Online (Sandbox Code Playgroud)


U10*_*ard 10

你可以使用json.loads

>>> import json
>>> json.loads('123.456')
123.456
>>> type(_)
<class 'float'>
>>> 
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,它变成了一种float.


Jer*_*y T 9

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')
Run Code Online (Sandbox Code Playgroud)


Nic*_*ick 6

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

即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)
Run Code Online (Sandbox Code Playgroud)

  • 好点子.这会导致通货膨胀,所以[Python 3](http://stackoverflow.com/questions/10825926/python-3-x-rounding-behavior)和[其他现代语言](http://stackoverflow.com/questions/311696/why-does-net-use-bankers-rounding-as-default)使用银行家的舍入. (4认同)
  • 这个答案是错误的(如最初所写)。它混淆了“ int”和“ float”这两种情况。而且,如果n是一个字符串,它将给出一个异常,这是OP所希望的。也许您的意思是:**当**希望得到“ int”结果时,应在转换为float后执行“ round”运算。如果函数应该总是返回一个int,那么您就不需要剩下的部分-整个函数体可以是int(round(float(input())))。如果函数尽可能返回一个int值,否则返回一个float值,那么javier的原始解决方案是正确的! (2认同)

Cyb*_*tic 6

将您的字符串传递给此函数:

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)
Run Code Online (Sandbox Code Playgroud)

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

一个 int 类型的字符串

print(type(string_to_number("124")))
<class 'int'>
Run Code Online (Sandbox Code Playgroud)

作为浮点数的字符串

print(type(string_to_number("12.4")))
<class 'float'>
Run Code Online (Sandbox Code Playgroud)

作为字符串的字符串

print(type(string_to_number("hello")))
<class 'str'>
Run Code Online (Sandbox Code Playgroud)

看起来像浮点数的字符串

print(type(string_to_number("hel.lo")))
<class 'str'>
Run Code Online (Sandbox Code Playgroud)

  • 在查看名称 `string_to_number` 时,我不希望它返回一个字符串。如果无法解析输入,我希望它会引发异常 (2认同)

Sła*_*art 5

我很惊讶没有人提到正则表达式,因为有时字符串必须准备并在转换为数字之前进行规范化

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
Run Code Online (Sandbox Code Playgroud)

用法:

parseNumber('13,345')
> 13345.0

parseNumber('- 123 000')
> -123000.0

parseNumber('99999\n')
> 99999.0
Run Code Online (Sandbox Code Playgroud)

顺便说一句,要验证你有一个数字:

import numbers
def is_number(value):
    return isinstance(value, numbers.Number)
    # will work with int, float, long, Decimal
Run Code Online (Sandbox Code Playgroud)


小智 5

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

例如:

>>>float("23.333")
   23.333
Run Code Online (Sandbox Code Playgroud)

在后台,python正在调用objects __float__方法,该方法应该返回参数的float表示形式。这是特别强大的功能,因为您可以使用__float__方法定义自己的类型(使用类),以便可以使用float(myobject)将其转换为float。


shr*_*use 5

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

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

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)
Run Code Online (Sandbox Code Playgroud)

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

======================== 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
Run Code Online (Sandbox Code Playgroud)

这是测试:

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)
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

3714955 次

最近记录:

5 年,9 月 前