Comment puis-je analyser une chaîne à un flotteur ou int?
-
22-08-2019 - |
Question
En Python, comment puis-je analyser une chaîne numérique comme "545.2222"
à sa valeur flottante correspondante, 545.2222
? Ou analyser la chaîne "31"
à un nombre entier, 31
?
Je veux juste savoir comment analyser un float str
à un float
et (séparément) un int str
à un int
.
La solution
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
Autres conseils
def num(s):
try:
return int(s)
except ValueError:
return float(s)
méthode Python pour vérifier si une chaîne est un float:
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)
Qu'est-ce qui est, et pas un flotteur dans peut 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 que vous savez ce que les chiffres sont? Vous n'êtes pas si bon que vous le pensez! Pas une grande surprise.
Ne pas utiliser ce code sur les logiciels critiques vie!
Attraper larges exceptions de cette façon, tuant les canaris et avalant l'exception crée une petite chance qu'un flotteur valide en tant que chaîne retournera false. La ligne de float(...)
de code peut pas pour l'une des mille raisons qui ont rien à voir avec le contenu de la chaîne. Mais si vous écrivez des logiciels critiques vie dans un langage de prototype en tapant le canard comme Python, alors vous avez des problèmes beaucoup plus importants.
Ceci est une autre méthode qui mérite d'être mentionné ici, ast.literal_eval :
Il peut être utilisé pour évaluer en toute sécurité des chaînes contenant des expressions Python provenant de sources non fiables, sans la nécessité d'analyser les valeurs soi-même.
C'est, 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)
Localisation et virgules
Vous devriez envisager 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. Au lieu de cela, utiliser des méthodes en locale
pour convertir les chaînes en nombres et interpréter correctement des virgules. La méthode de locale.atof
convertit en un flotteur en une seule étape une fois que la localisation a été fixée pour la convention de numéro souhaité.
Exemple 1 - Conventions de numérotation des États-Unis
Aux États-Unis et au Royaume-Uni, les virgules peuvent être utilisés comme séparateur de milliers. Dans cet exemple, avec locale américaine, la virgule est traitée correctement comme 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 - les conventions de numérotation européen
Dans la majorité des pays du monde , les virgules sont utilisés pour les marques décimales au lieu des périodes. Dans cet exemple avec paramètres régionaux français, la virgule est traitée correctement 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é à des modules tiers, vous pouvez consulter le module fastnumbers . Il offre une fonction appelée fast_real qui fait exactement ce que cette question est demander 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
Utilisateurs codelogic et harley sont corrects, mais gardez à l'esprit si vous connaissez la chaîne est un entier (par exemple, 545), vous pouvez appeler int ( "545" ) sans coulée à flotter.
Si vos chaînes sont dans une liste, vous pouvez utiliser la fonction de carte ainsi.
>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>
Il est bon que s'ils sont tous du même type.
La question semble un peu vieux. Mais permettez-moi de suggérer une fonction, parseStr, ce qui en fait quelque chose de similaire, qui est, retourne entière ou flottante et si une chaîne ASCII donnée ne peut pas être converti en aucun d'eux retourne intact. Le code de cours peut ê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$5')
'12$5'
>>> parseStr('12.2.2')
'12.2.2'
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 nombre entier, 31? Je veux juste savoir comment analyser une chaîne de flotteur à un flotteur, et (séparément) une chaîne int à un int.
Il est bon que vous demandez de faire séparément. Si vous les mélanger, vous pouvez vous mettre en place pour les problèmes plus tard. La réponse est simple:
"545.2222"
flotter:
>>> float("545.2222")
545.2222
"31"
à un nombre entier:
>>> int("31")
31
D'autres conversions, ints et à partir de chaînes et littéraux:
Les conversions de différentes bases, et vous devez 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é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 vous ne savent qu'ils auront le préfixe correct, Python peut déduire pour vous si vous passez 0
comme base:
>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31
Non-décimal (à savoir Integer) littéraux d'autres bases
Si votre motivation est d'avoir votre propre code représentent clairement des valeurs spécifiques codées en dur, mais vous ne pouvez pas besoin de convertir des bases -. Vous pouvez laisser Python faire pour vous automatiquement avec la syntaxe correcte
Vous pouvez utiliser les préfixes apropos pour obtenir la conversion automatique en nombres entiers avec la chaînes suivantes . Ceux-ci sont valables pour Python 2 et 3:
Binary, 0b
préfixe
>>> 0b11111
31
Octal, 0o
préfixe
>>> 0o37
31
Hexadécimal, 0x
préfixe
>>> 0x1f
31
Cela peut être utile pour décrire des drapeaux binaires, les permissions de fichiers dans le code, ou des valeurs hexagonales pour les couleurs - par exemple, la note sans 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 Python ambiguë 2 octal compatible avec Python 3
Si vous voyez un entier qui commence par un 0, en Python 2, c'est (dépréciée) syntaxe octal.
>>> 037
31
Il est mauvais parce qu'il ressemble devrait être 37
la valeur. Donc, en Python 3, il soulève maintenant un SyntaxError
:
>>> 037
File "<stdin>", line 1
037
^
SyntaxError: invalid token
Convertir votre Python 2 octal à octal qui travaillent dans les deux 2 et 3 avec le préfixe 0o
:
>>> 0o37
31
float("545.2222")
et int(float("545.2222"))
>>> 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'>
J'utilise cette fonction pour que
import ast
def parse_str(s):
try:
return ast.literal_eval(str(s))
except:
return
Il convertit la chaîne à son type
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')
Vous devez prendre en compte l'arrondissement de le faire correctement.
i.e.. int (5,1) => 5 int (5,6) => 5 - mal, devrait être 6 donc nous 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 mentionné regex parce que parfois la chaîne doit être préparée et normalisée avant la coulée 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 par la manière, quelque chose à vérifier que vous avez un certain nombre:
import numbers
def is_number(value):
return isinstance(value, numbers.Number)
# will work with int, float, long, Decimal
Pour cataloguée en python utiliser le constructeur funtions du type, en passant la chaîne (ou quelle que soit la valeur que vous essayez de lancer) comme paramètre.
Par exemple:
>>>float("23.333")
23.333
Dans les coulisses, python appelle les objets méthode __float__
, qui doit retourner une représentation flottante du paramètre. Cela est particulièrement puissant, comme vous pouvez définir vos propres types (en utilisant des classes) avec une méthode de __float__
afin qu'il puisse être casté en un flotteur en utilisant flotteur (myobject).
Ceci est une version corrigée https://stackoverflow.com/a/33017514/5973334
va essayer d'analyser une chaîne et retourner soit int
ou float
en fonction de ce que représente la chaîne.
Il pourrait augmenter les exceptions d'analyse syntaxique ou ont 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
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()
Ceci est la façon la plus Pythonic je pouvais trouver.
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'>
Ceci est une fonction qui vous permet de convertir une object
(pas seulement str
) à int
ou float
, sur la base si la chaîne réelle fournie ressemble int
ou float
. En outre, si elle est un objet qui a deux méthodes de __float
et __int__
, il est par défaut à l'aide __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
Voici une autre interprétation de votre question (indice: il est vague). Il est possible que vous cherchez quelque chose comme ceci:
def parseIntOrFloat( aString ):
return eval( aString )
Il fonctionne comme ça ...
>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545
En théorie, il y a une vulnérabilité d'injection. La chaîne pourrait, par exemple, être "import os; os.abort()"
. Sans arrière-plan sur lequel la chaîne vient, cependant, la possibilité est la spéculation théorique. Étant donné que la question est vague, ce n'est pas du tout clair si cette vulnérabilité existe réellement ou non.