¿Cómo analizar una cadena a un flotador o int?
-
22-08-2019 - |
Pregunta
En Python, ¿cómo puedo analizar una cadena alfanumérica como "545.2222"
a su correspondiente valor de tipo float, 545.2222
?O analizar la cadena "31"
para un entero, 31
?
Sólo quiero saber cómo analizar un flotador str
a un float
, y (por separado) un int str
a un int
.
Solución
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
Otros consejos
def num(s):
try:
return int(s)
except ValueError:
return float(s)
Python método para comprobar si una cadena es un flotador:
def is_float(value):
try:
float(value)
return True
except:
return False
Un nombre más largo y más preciso para esta función podría ser: is_convertible_to_float(value)
¿Qué es, y no es un flotador en Python que puede sorprender:
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
Se cree que sabe lo que son los números? Usted no es tan bueno como usted piensa! No es una gran sorpresa.
No utilizar este código en el software críticos para la vida!
La captura de amplias excepciones de esta manera, matando a los canarios y tragándose la excepción crea una pequeña posibilidad de que un flotador válida como cadena volverá falsa. La línea de código puede float(...)
fallado por alguna de las mil razones que no tienen nada que ver con el contenido de la cadena. Pero si usted está escribiendo el software críticos para la vida en un idioma prototipo de pato a escribir como Python, entonces usted tiene problemas mucho más grandes.
Este es otro método que merece ser mencionado aquí, ast.literal_eval :
Esto puede ser usado para evaluar de forma segura cadenas que contengan expresiones Python de fuentes no fiables sin la necesidad de analizar los valores de uno mismo.
Es decir, un 'eval' segura
>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
float(x) if '.' in x else int(x)
Localización y comas
Debe tener en cuenta la posibilidad de comas en la representación de cadena de un número, por casos como float("545,545.2222")
la que se produce una excepción. En su lugar, utilizar métodos en locale
para convertir las cadenas en números e interpretar correctamente las comas. El método locale.atof
convierte a un flotador en un solo paso una vez que la configuración regional se ha establecido para la convención número deseado.
Ejemplo 1 - Estados Unidos número convenciones
En los Estados Unidos y el Reino Unido, las comas se pueden utilizar como un separador de miles. En este ejemplo, con la configuración regional de América, la coma se maneja adecuadamente 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 - European convenciones de numeración
En el mayoría de los países del mundo , comas se utilizan para las marcas decimales en lugar de períodos. En este ejemplo con el entorno local francés, 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 locale.atoi
método también está disponible, pero el argumento debe ser un entero.
Si no es contrario a los módulos de terceros, se puede consultar la fastnumbers módulo. Se proporciona una función llamada fast_real que hace exactamente lo que esta pregunta es 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
Usuarios codelogic y Harley son correctas, pero tenga en cuenta si conoce la cadena es un número entero (por ejemplo, 545) puede llamar a int ( "545" ) sin primero fundición a flotar.
Si las cuerdas están en una lista, puede utilizar la función de mapa así.
>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>
Es sólo es bueno si son todos del mismo tipo.
La pregunta parece un poco viejo. Pero permítanme sugerir una función, parseStr, lo que hace algo similar, es decir, vuelve entero o flotar y si una cadena ASCII dado no se puede convertir en ninguno de ellos se lo devuelve intacto. El código, por supuesto, podría ser ajustado para hacer lo que desee:
>>> 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'
En Python, ¿cómo puedo analizar una cadena alfanumérica como "545.2222" a su correspondiente valor de tipo float, 542.2222?O analizar la cadena "31" a un entero, 31? Sólo quiero saber cómo analizar un float string a un flotador, y (por separado) int string int.
Es bueno que pedir por separado.Si estás mezcla de ellos, puede ser el establecimiento de sí mismo para problemas más adelante.La respuesta simple es:
"545.2222"
flotar:
>>> float("545.2222")
545.2222
"31"
para un entero:
>>> int("31")
31
Otras conversiones, enteros y de las cadenas y los literales:
Las conversiones a partir de distintas bases, y usted debe saber la base de anticipación (10 es el valor predeterminado).Nota puede prefijo de ellos con lo de Python espera para su literales (ver más abajo) o quitar 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 usted no sabe la base de anticipación, pero usted sabe que va a tener el prefijo correcto, Python puede inferir esto para usted si usted pase 0
como la base:
>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31
No Decimales (es decir,Entero) Literales de otras Bases
Si tu motivación es tener su propio código de representar claramente codificado valores específicos, sin embargo, puede que no necesite para convertir desde las bases - usted puede dejar de Python hacer automáticamente con la sintaxis correcta.
Usted puede utilizar el propósito de prefijos para obtener una conversión automática a números enteros con los siguientes literales.Estos son válidas para Python 2 y 3:
El binario, el prefijo 0b
>>> 0b11111
31
Octal, prefijo 0o
>>> 0o37
31
Hexadecimal, prefijo 0x
>>> 0x1f
31
Esto puede ser útil cuando se describe el binario banderas, los permisos de archivo en el código, o valores hexadecimales de los colores - por ejemplo, la nota de sin 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
Hacer ambigua Python 2 octals compatible con Python 3
Si usted ve un número entero que comienza con un 0, en Python 2, esto es (en desuso) octal sintaxis.
>>> 037
31
Es malo porque se ve como el valor debe ser 37
.Así que en Python 3, ahora se plantea una SyntaxError
:
>>> 037
File "<stdin>", line 1
037
^
SyntaxError: invalid token
Convertir tu Python 2 octals a octals que trabajar en 2 y 3 con la 0o
prefijo:
>>> 0o37
31
float("545.2222")
y int(float("545.2222"))
El analizador YAML puede ayudar a determinar qué tipo de datos es la cadena. Utilice yaml.load()
, y luego se puede utilizar para probar type(result)
para 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'>
Yo uso esta función para la que
import ast
def parse_str(s):
try:
return ast.literal_eval(str(s))
except:
return
Será convertir la cadena en su tipo
value = parse_str('1') # Returns Integer
value = parse_str('1.5') # Returns Float
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):
"""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')
Es necesario tomar en cuenta el redondeo para hacer esto correctamente.
es decir. int (5,1) => 5 int (5,6) => 5 - mal, debe ser de 6 por lo que hacemos int (5,6 + 0,5) => 6
def convert(n):
try:
return int(n)
except ValueError:
return float(n + 0.5)
Me sorprende que nadie ha mencionado expresiones regulares porque a veces cadena debe ser preparado y se normalizó antes de emitir el 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 que compruebe que tiene un número:
import numbers
def is_number(value):
return isinstance(value, numbers.Number)
# will work with int, float, long, Decimal
Para encasillado en Python utilizar las funtions de constructor de la clase, pasando la cadena (o cualquier valor que está tratando de fundido) como parámetro.
Por ejemplo:
>>>float("23.333")
23.333
Entre bastidores, pitón está llamando a los objetos __float__
método, que debe devolver una representación de flotación del parámetro. Esto es especialmente potente, como se puede definir sus propios tipos (el uso de clases) con un método __float__
de modo que se puede lanzar en un flotador usando flotador (myObject).
Esta es una versión corregida de https://stackoverflow.com/a/33017514/5973334
Esto va a tratar de analizar una cadena y regresar ya sea int
o float
dependiendo de lo que la cadena representa.
Podría elevarse excepciones de análisis o tienen un 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
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 Pythonic que podía ocurrir.
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'>
Esta es una función que convertirá cualquier object
(no sólo str
) a int
o float
, sobre la base de si la cadena real proporcionada ve como int
o float
. Además si se trata de un objeto que tiene ambos métodos __float
y __int__
, el valor predeterminado es el uso de __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
Aquí hay otra interpretación de su pregunta (pista: es vaga). Es posible que estés buscando algo como esto:
def parseIntOrFloat( aString ):
return eval( aString )
Funciona de la siguiente ...
>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545
En teoría, hay una vulnerabilidad de inyección. La cadena puede ser, por ejemplo "import os; os.abort()"
. Sin ningún tipo de fondo en donde la cadena viene, sin embargo, la posibilidad es la especulación teórica. Dado que la cuestión es vago, no es del todo claro si esta vulnerabilidad existe realmente o no.