¿Cómo puedo analizar una cadena a un float o int en Python?


En Python, ¿cómo puedo analizar una cadena numérica como "545.2222" a su correspondiente valor flotante, 542.2222? O analizar la cadena "31" a un entero, 31?

Solo quiero saber cómo analizar un flotador string a float, y (por separado) a int string a un int.

Author: Steven Vascellaro, 2008-12-19

23 answers

>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
 2142
Author: Harley Holcombe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-19 01:54:51
def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)
 453
Author: Javier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-08 12:20:41

Método Python para comprobar si una cadena es flotante:

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

Un nombre más largo y preciso para esta función podría ser: is_convertible_to_float(value)

Lo que es y no es un flotador en Python puede sorprenderte:

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

¿Crees que sabes qué son los números? ¡No eres tan bueno como crees! No es una gran sorpresa.

 427
Author: Eric Leschinski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-22 17:51:07

Este es otro método que merece ser mencionado aquí, ast.literal_eval :

Esto se puede usar para evaluar de forma segura cadenas que contienen expresiones de Python de fuentes no confiables sin la necesidad de analizar los valores uno mismo.

Es decir, una "evaluación" segura

>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
 108
Author: wim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-15 02:23:45
float(x) if '.' in x else int(x)
 75
Author: Dino Viehland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-19 02:33:15

Localización y comas

Debe considerar la posibilidad de comas en la representación de cadena de un número, para casos como float("545,545.2222") que arroja una excepción. En su lugar, use métodos en locale para convertir las cadenas a números e interpretar las comas correctamente. El método locale.atof se convierte en un flotador en un paso una vez que se ha establecido la configuración regional para la convención numérica deseada.

Ejemplo 1-Convenios numéricos de los Estados Unidos

En los Estados Unidos y el Reino Unido, las comas se pueden utilizar como un separador de miles. En este ejemplo con American locale, la coma se maneja correctamente como separador:

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

Ejemplo 2 conventions Convenios numéricos europeos

En la mayoría de los países del mundo, las comas se utilizan para marcas decimales en lugar de puntos. En este ejemplo con French locale, la coma se maneja correctamente como una marca decimal:

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

El método locale.atoi también está disponible, pero el argumento debe ser un entero.

 48
Author: Mark Chackerian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-06 23:29:46

Los usuarios codelogic y harley son correctos, pero tenga en cuenta que si sabe que la cadena es un entero (por ejemplo, 545), puede llamar a int("545") sin primero lanzar a float.

Si sus cadenas están en una lista, también podría usar la función map.

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

Solo es bueno si todos son del mismo tipo.

 23
Author: Chris Cameron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-21 08:28:35

Si no eres reacio a los módulos de terceros, puedes revisar el módulo fastnumbers. Proporciona una función llamada fast_real que hace exactamente lo que esta pregunta está pidiendo y lo hace más rápido que una implementación de Python puro:

>>> 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
 22
Author: SethMMorton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-20 02:48:49

En Python, ¿cómo puedo analizar una cadena numérica como "545.2222" a su correspondiente valor flotante, 542.2222? O analizar la cadena "31" a un entero, 31? Solo quiero saber cómo analizar una cadena flotante a un flotador, y (por separado) una cadena int a un int.

Es bueno que pidas hacer esto por separado. Si los estás mezclando, es posible que te estés preparando para problemas más tarde. La respuesta simple es:

"545.2222" to flotador:

>>> float("545.2222")
545.2222

"31" a un entero:

>>> int("31")
31

Otras conversiones, ints hacia y desde cadenas y literales:

Conversiones de varias bases, y debe conocer la base de antemano (10 es el valor predeterminado). Tenga en cuenta que puede prefijarlos con lo que Python espera para sus literales (ver más abajo) o eliminar el prefijo:

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

Si no conoces la base de antemano, pero sabes que tendrán el prefijo correcto, Python puede inferir esto por ti si pasar 0 como base:

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

Literales no decimales (es decir, Enteros) de otras Bases

Si su motivación es tener su propio código claramente representa valores específicos codificados, sin embargo, es posible que no necesite convertir desde las bases-puede dejar que Python lo haga por usted automáticamente con la sintaxis correcta.

Puede usar los prefijos de apropos para obtener la conversión automática a enteros con los siguientes literales. Estos son válidos para Python 2 y 3:

Binario, prefijo 0b

>>> 0b11111
31

Octal, prefijo 0o

>>> 0o37
31

Hexadecimal, prefijo 0x

>>> 0x1f
31

Esto puede ser útil cuando se describen banderas binarias, permisos de archivo en código o valores hexadecimales para colores, por ejemplo, no tenga en cuenta comillas:

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

Haciendo que los octales ambiguos de Python 2 sean compatibles con Python 3

Si ve un entero que comienza con un 0, en Python 2, esta es una sintaxis octal (obsoleta).

>>> 037
31

Es malo porque parece que el valor debería ser 37. Así que en Python 3, ahora plantea un SyntaxError:

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

Convierta sus octales de Python 2 a octales que funcionen tanto en 2 como en 3 con el prefijo 0o:

>>> 0o37
31
 18
Author: Aaron Hall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-27 15:07:40

La pregunta parece un poco vieja. Pero permítanme sugerir una función, parseStr, que hace algo similar, es decir, devuelve entero o flotante y si una cadena ASCII dada no se puede convertir a ninguna de ellas, la devuelve intacta. El código, por supuesto, podría ajustarse para hacer solo lo que desea:

   >>> 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'
 17
Author: krzym,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-21 08:32:25

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

 15
Author: codelogic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-19 01:54:11

El analizador sintáctico YAML puede ayudarlo a averiguar qué tipo de datos es su cadena. Use yaml.load(), y luego puede usar type(result) para probar el tipo:

>>> 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'>
 13
Author: Rafe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-21 08:33:48
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
 11
Author: Totoro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-30 11:39:49

Uso esta función para eso

import ast

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

Convertirá la cadena a su tipo

value = parse_str('1')  # Returns Integer
value = parse_str('1.5')  # Returns Float
 8
Author: Shameem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-25 05:32:04

Debe tener en cuenta el redondeo para hacer esto correctamente.

Es decir, int (5.1) = > 5 int (5.6) = > 5 wrong incorrecto, debe ser 6 así que hacemos int(5.6 + 0.5) => 6

def convert(n):
    try:
        return int(n)
    except ValueError:
        return float(n + 0.5)
 7
Author: Nick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-21 14:10:01
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')
 7
Author: Jerry T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-09 18:04:52

Esta es una versión corregida de https://stackoverflow.com/a/33017514/5973334

Esto intentará analizar una cadena y devolver int o float dependiendo de lo que representa la cadena. Podría aumentar las excepciones de análisis o tener algún comportamiento inesperado.

  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
 3
Author: Kuzeko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:19

Me sorprende que nadie mencionara regex porque a veces la cadena debe prepararse y normalizarse antes de lanzarse a número

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

Uso:

parseNumber('13,345')
> 13345.0

parseNumber('- 123 000')
> -123000.0

parseNumber('99999\n')
> 99999.0

Y por cierto, algo para verificar que tienes un número:

import numbers
def is_number(value):
    return isinstance(value, numbers.Number)
    # will work with int, float, long, Decimal
 3
Author: Sławomir Lenart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-12 17:01:41

Python tiene esta gran flexibilidad de analizar en un liner.

str = "545.2222"
print ("int: ", + int(float(a)))
print ("float: ", +(float(a)))
 3
Author: Harry_pb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-01 16:32:27

Para encasillar en python use las funciones del constructor del tipo, pasando la cadena (o cualquier valor que esté tratando de convertir) como parámetro.

Por ejemplo:

>>>float("23.333")
   23.333

Entre bastidores, python está llamando al método objects __float__, que debería devolver una representación flotante del parámetro. Esto es especialmente poderoso, ya que puede definir sus propios tipos (usando clases) con un método __float__ para que pueda ser fundido en un flotador usando float(myobject).

 2
Author: qwerty12345,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-01 20:42:31

Uso:

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()

Esta es la forma más pitónica que se me ocurrió.

 1
Author: SeasonalShot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-14 15:05:50

Uso:

>>> 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'>
 0
Author: ateymuri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-14 15:06:15

Aquí hay otra interpretación de su pregunta (pista: es vaga). Es posible que esté buscando algo como esto:

def parseIntOrFloat( aString ):
    return eval( aString )

Funciona así...

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

Teóricamente, hay una vulnerabilidad de inyección. La cadena podría, por ejemplo, ser "import os; os.abort()". Sin ningún antecedente sobre de dónde proviene la cadena, sin embargo, la posibilidad es especulación teórica. Dado que la pregunta es vaga, no está del todo claro si esta vulnerabilidad realmente existe o no.

 -13
Author: S.Lott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-21 08:30:04