En Python, comment analyser une chaîne numérique telle que "545.2222"
vers sa valeur flottante correspondante, 545.2222
? Ou analyser la chaîne "31"
en un entier, 31
?
Je veux juste savoir comment analyser un floatstr
à un float
, et (séparément) un intstr
à un int
.
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
def num(s):
try:
return int(s)
except ValueError:
return float(s)
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)
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 quels sont les chiffres? Vous n'êtes pas aussi bon que vous le pensez! Pas grande surprise.
Catching large exceptions de cette façon, tuer les canaris et engloutir l'exception crée une infime chance qu'un float valide en tant que chaîne retournera false. La ligne de code float(...)
peut échouer pour mille raisons n'ayant rien à voir avec le contenu de la chaîne. Mais si vous écrivez un logiciel essentiel à la vie dans un prototype de langage de typage, comme Python, vous avez des problèmes bien plus importants.
C’est une autre méthode qui mérite d’être mentionnée ici, ast.literal_eval :
Cela peut être utilisé pour évaluer en toute sécurité des chaînes contenant des expressions Python de sources non fiables sans avoir à analyser elles-mêmes les valeurs.
C'est-à-dire un coffre-fort 'eval'
>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
float(x) if '.' in x else int(x)
Vous devriez envisager la possibilité d'utiliser des virgules dans la représentation sous forme de chaîne d'un nombre, dans des cas comme float("545,545.2222")
qui lève 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
est convertie en un nombre flottant en une étape une fois que les paramètres régionaux ont été définis pour la convention de nombre souhaitée.
Exemple 1 - Conventions de numérotation des États-Unis
Aux États-Unis et au Royaume-Uni, les virgules peuvent être utilisées comme séparateur de milliers. Dans cet exemple avec les paramètres régionaux américains, la virgule est gérée correctement en tant que 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 de numérotation européennes
Dans le majorité des pays du monde , les virgules sont utilisées pour les marques décimales au lieu de points. Dans cet exemple avec les paramètres régionaux français, la virgule est correctement géré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 entier.
Si vous n'êtes pas opposé aux modules tiers, vous pouvez consulter le module fastnumbers . 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
Les utilisateurs codelogic et harley sont corrects, mais n'oubliez pas que si vous savez que la chaîne est un entier (par exemple, 545), vous pouvez appeler int ("545") sans d'abord couler pour flotter.
Si vos chaînes figurent dans une liste, vous pouvez également utiliser la fonction map.
>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>
Ce n'est bien que s'ils sont tous du même type.
La question semble un peu vieille. Mais permettez-moi de suggérer une fonction, parseStr, qui rend quelque chose de similaire, c'est-à-dire qui renvoie un entier ou un flottant et si une chaîne donnée ASCII ne peut être convertie en aucune de ces chaînes, elle la renvoie telle quelle. Le code bien sûr peut être ajusté pour ne faire que 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$5')
'12$5'
>>> parseStr('12.2.2')
'12.2.2'
En Python, comment analyser une chaîne numérique telle que "545.2222" avec sa valeur float correspondante, 542.2222? Ou analyser la chaîne "31" en un entier, 31? Je veux juste savoir comment analyser une chaîne float en un flottant, et (séparément) une chaîne int en un int.
C'est bien que vous demandiez de les faire séparément. Si vous les mélangez, il se peut que vous vous prépariez à des problèmes plus tard. La réponse simple est:
"545.2222"
pour flotter:
>>> float("545.2222")
545.2222
"31"
en un entier:
>>> int("31")
31
Conversions à partir de différentes bases et vous devez connaître la base à l’avance (10 par défaut). Notez que vous pouvez les préfixer avec ce que Python attend pour ses littéraux (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 que vous savez qu'ils auront le bon préfixe, Python peut en déduire cela si vous passez 0
comme base:
>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31
Si votre motivation est de faire en sorte que votre propre code représente clairement des valeurs spécifiques codées en dur, vous n'avez peut-être pas besoin de convertir à partir des bases - vous pouvez laisser Python le faire pour vous automatiquement avec la syntaxe correcte.
Vous pouvez utiliser les préfixes apropos pour obtenir la conversion automatique en nombres entiers avec les littéraux suivants . 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 lorsque vous décrivez des indicateurs binaires, des autorisations de fichier dans du code ou des valeurs hexadécimales pour les couleurs. Par exemple, ne 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
Si vous voyez un entier commençant par 0, dans Python 2, il s'agit d'une syntaxe octale (obsolète).
>>> 037
31
C'est mauvais parce qu'il semble que la valeur devrait être 37
. Donc, dans Python 3, il soulève maintenant un SyntaxError
:
>>> 037
File "<stdin>", line 1
037
^
SyntaxError: invalid token
Convertissez vos Python 2 octals en octaux qui fonctionnent à la fois en 2 et en 3 avec le préfixe 0o
:
>>> 0o37
31
float("545.2222")
et int(float("545.2222"))
J'utilise cette fonction pour ça
import ast
def parse_str(s):
try:
return ast.literal_eval(str(s))
except:
return
Il va convertir la chaîne à son type
value = parse_str('1') # Returns Integer
value = parse_str('1.5') # Returns Float
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
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')
Vous devez tenir compte de l'arrondissement pour le faire correctement.
C'est à dire. int (5.1) => 5 int (5.6) => 5 - faux, devrait être 6, donc int (5.6 + 0.5) => 6
def convert(n):
try:
return int(n)
except ValueError:
return float(n + 0.5)
Je suis surpris que personne ne mentionne regex car parfois, la chaîne doit être préparée et normalisée avant la conversion en nombre
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
usage:
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
Pour transtyper en python, utilisez les fonctions de constructeur du type, en transmettant la chaîne (ou la valeur que vous essayez de convertir) en tant que paramètre.
Par exemple:
>>>float("23.333")
23.333
En coulisse, python appelle la méthode des objets __float__
, qui devrait renvoyer une représentation flottante 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__
afin de pouvoir le transformer en float en utilisant float (myobject).
Python a cette grande souplesse d’analyse dans un liners.
str = "545.2222"
print ("int: ", + int(float(a)))
print ("float: ", +(float(a)))
Ceci est une version corrigée de https://stackoverflow.com/a/33017514/5973334
Cela essaiera d'analyser une chaîne et retournera soit int
ou float
en fonction de ce que la chaîne représente. Il se peut que des exceptions d'analyse ou aient un 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
Vous pouvez utiliser str()
pour convertir toute variable en chaîne, int()
pour convertir des entiers de chaîne en entiers et float()
pour convertir des nombres flottants de chaîne en valeurs flottantes.
str_to_float = float("545.2222")
str_to_int = int("31")
Utilisation:
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 la manière la plus pythonique que je puisse trouver.
C'est une fonction qui convertira toute object
(pas seulement str
) en int
ou float
, en fonction du fait que la chaîne réelle fournie ressemble à = int
ou float
. De plus, si c'est un objet qui a à la fois les méthodes __float
et __int__
, il utilise par défaut __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
Utilisation:
>>> 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'>