Comment puis-je analyser une chaîne à un float ou à un int en Python?
en Python, Comment puis-je analyser une chaîne numérique comme "545.2222"
à sa valeur flottante correspondante, 542.2222
? Ou analyser la chaîne "31"
à un entier, 31
?
je veux juste savoir comment analyser un float string
à un float
, et (séparément) un int string
à une int
.
23 réponses
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
def num(s):
try:
return int(s)
except ValueError:
return float(s)
méthode Python pour vérifier si une chaîne est un flotteur:
def is_float(value):
try:
float(value)
return True
except:
return False
un nom plus long et plus précis pour cette fonction pourrait être: is_convertible_to_float(value)
Ce qui est, et n'est pas un flotteur dans Python peut-être vous surprendre:
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
vous pensez savoir ce que sont les nombres? Vous n'êtes pas aussi bon que vous le pensez! Pas de grosse surprise.
c'est une autre méthode qui mérite d'être mentionnée ici, ast.littéral_eval :
ceci peut être utilisé pour évaluer en toute sécurité des chaînes contenant des expressions Python de sources non fiables sans avoir à analyser les valeurs soi-même.
C'est-à-dire une "évaluation" sûre 151940920"
>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
localisation et virgules
vous devriez considérer la possibilité de virgules dans la représentation de chaîne d'un nombre, pour des cas comme float("545,545.2222")
qui jette une exception. Utilisez plutôt les méthodes de locale
pour convertir les chaînes en nombres et interpréter correctement les virgules. La méthode locale.atof
convertit en un flottant en une étape une fois que la locale a été définie pour la convention de nombre désirée.
Exemple 1 -- United États nombre conventions
aux États-Unis et au Royaume-Uni, les virgules peuvent être utilisées comme séparateur de milliers. Dans cet exemple avec American locale, la virgule est traitée correctement comme un séparateur:
>>> 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
>>>
exemple 2 -- conventions du numéro européen
"dans le la majorité des pays du monde , les virgules sont utilisées pour les marques décimales au lieu des périodes. Dans cet exemple avec LA locale FRANÇAISE, la virgule est correctement traitée comme une marque décimale:
>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222
La méthode locale.atoi
est également disponible, mais l'argument doit être un nombre entier.
Utilisateurs codelogic et harley sont correctes, mais gardez à l'esprit si vous connaissez la chaîne est un nombre entier (par exemple, 545), vous pouvez appeler int("545") sans premier casting de flotter.
Si vos cordes sont dans une liste, vous pouvez utiliser la fonction map.
>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>
ce n'est bon que s'ils sont tous du même type.
si vous n'êtes pas contre les modules tiers, vous pouvez consulter le module fastnumber . Il fournit une fonction appelée fast_real qui fait exactement ce que cette question demande et le fait plus rapidement qu'une implémentation pure-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
en Python, Comment puis-je analyser une chaîne numérique comme "545.2222" à sa valeur flottante correspondante, 542.2222? Ou parse la chaîne "31" à un entier, 31? Je veux juste savoir comment analyser une chaîne de flotteurs en flotteurs, et (séparément) une chaîne int en int.
il est bon que vous demandiez de les faire séparément. Si vous les mélangez, vous pourriez vous préparer à des problèmes plus tard. La réponse est simple:
"545.2222"
pour flotter:
>>> float("545.2222")
545.2222
"31"
à un entier:
>>> int("31")
31
autres conversions, en et à partir de cordes et littérales:
Conversions à partir de différentes bases, et vous devriez connaître la base à l'avance (10 est la valeur par défaut). Notez que vous pouvez les préfixer avec ce que Python attend pour ses littérales (voir ci-dessous) ou supprimer le préfixe:
>>> 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 vous ne connaissez pas la base à l'avance, mais vous savez qu'ils auront le bon préfixe, Python peut inférer cela pour vous si vous passez 0
comme base:
>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31
littérales Non décimales (C'est-à-dire entières) à partir d'autres Bases
si votre motivation est d'avoir votre propre code représente clairement des valeurs spécifiques codées, cependant, vous pouvez ne pas avoir besoin de convertir à partir des bases - vous pouvez laisser Python le fait pour vous automatiquement avec la syntaxe correcte.
vous pouvez utiliser les préfixes apropos pour obtenir la conversion automatique en entiers avec les littérales suivantes . Ceux-ci sont valables pour Python 2 et 3:
binaire, préfixe 0b
>>> 0b11111
31
Octal, préfixe 0o
>>> 0o37
31
hexadécimal, préfixe 0x
>>> 0x1f
31
cela peut être utile pour décrire des drapeaux binaires, des permissions de fichiers en code, ou des valeurs hexadécimales pour les couleurs - par exemple, notez pas de guillemets:
>>> 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
Faire ambigu Python 2 octals compatible avec Python 3
si vous voyez un entier qui commence par un 0, en Python 2, c'est la syntaxe octale (dépréciée).
>>> 037
31
il est mauvais parce qu'il ressemble à la valeur devrait être 37
. Donc en Python 3, Il soulève maintenant un SyntaxError
:
>>> 037
File "<stdin>", line 1
037
^
SyntaxError: invalid token
Convertissez vos octals Python 2 en octals qui fonctionnent en 2 et 3 avec le préfixe 0o
:
>>> 0o37
31
la question semble un peu vieille. Mais permettez-moi de Suggérer une fonction, parseStr, qui fait quelque chose de similaire, c'est-à-dire retourne entier ou flotter et si une chaîne ASCII donnée ne peut pas être convertie à aucun d'eux, il renvoie intact. Le code pourrait bien sûr être ajusté pour faire seulement ce que vous voulez:
>>> 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')
'12'
>>> parseStr('12.2.2')
'12.2.2'
L'analyseur YAML peut vous aider à déterminer le type de données de votre chaîne. Utilisez yaml.load()
, puis vous pouvez utiliser type(result)
pour tester le type:
>>> 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 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
j'utilise cette fonction pour que
import ast
def parse_str(s):
try:
return ast.literal_eval(str(s))
except:
return
il convertira la chaîne en son type
value = parse_str('1') # Returns Integer
value = parse_str('1.5') # Returns Float
vous devez tenir compte de l'arrondissement pour le faire correctement.
i. e. int (5.1) => 5 int(5.6) => 5 -- mal, devrait être de 6, de sorte que nous ne nous int(5.6 + 0.5) => 6
def convert(n):
try:
return int(n)
except ValueError:
return float(n + 0.5)
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')
C'est une version corrigée de https://stackoverflow.com/a/33017514/5973334
cela va essayer d'analyser une chaîne de caractères et de retourner soit int
ou float
selon ce que la chaîne représente.
Il pourrait augmenter les exceptions d'analyse ou ont un certain comportement inattendu .
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
je suis surpris que personne n'ait mentionné regex parce que parfois la corde doit être préparée et normalisée avant le moulage au numéro
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
utilisation:
parseNumber('13,345')
> 13345.0
parseNumber('- 123 000')
> -123000.0
parseNumber('99999\n')
> 99999.0
et au fait, quelque chose pour vérifier que vous avez un numéro:
import numbers
def is_number(value):
return isinstance(value, numbers.Number)
# will work with int, float, long, Decimal
Python ont cette grande flexibilité de parsing en une seule couche.
str = "545.2222"
print ("int: ", + int(float(a)))
print ("float: ", +(float(a)))
pour typecast en python utilisez les fonctions du constructeur du type, en passant la chaîne (ou n'importe quelle valeur que vous essayez de lancer) comme paramètre.
par exemple:
>>>float("23.333")
23.333
dans les coulisses, python appelle les objets la méthode __float__
, qui devrait retourner une représentation float du paramètre. Ceci est particulièrement puissant, car vous pouvez définir vos propres types (en utilisant des classes) avec une méthode __float__
de sorte qu'il peut être intégré dans un flotteur à l'aide du flotteur(monobjet).
utiliser:
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()
C'est le moyen le plus pythonique que j'ai pu trouver.
utiliser:
>>> 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'>
voici une autre interprétation de votre question (indice: c'est vague). Il est possible que vous cherchiez quelque chose comme ceci:
def parseIntOrFloat( aString ):
return eval( aString )
ça marche comme ça...
>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545
théoriquement, il y a une vulnérabilité d'injection. La chaîne pourrait, par exemple, être "import os; os.abort()"
. Sans aucun arrière-plan sur l'origine de la chaîne, cependant, la possibilité est la spéculation théorique. Puisque la question Est vague, ce n'est pas du tout clair si cette vulnérabilité existe ou non.