web-dev-qa-db-fra.com

Comment analyser une chaîne avec un float ou un int?

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.

2056
Tristan Havelick
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
2417
Harley Holcombe
def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)
483
Javier

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)

Ce qui est et n’est pas un float dans Python 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 savoir quels sont les chiffres? Vous n'êtes pas aussi bon que vous le pensez! Pas grande surprise.

N'utilisez pas ce code sur des logiciels critiques!

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.

474
Eric Leschinski

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
121
wim
float(x) if '.' in x else int(x)
75
Dino Viehland

Localisation et virgules

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.

60
Mark Chackerian

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

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.

24
Chris Cameron

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'
19
krzym

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

Autres conversions, entrées et sorties de chaînes et de littéraux:

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

Littéraux non décimaux (c'est-à-dire entiers) d'autres bases

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

Rendre Python _ 2 octaux ambigu compatible avec Python 3

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
19
Aaron Hall

float("545.2222") et int(float("545.2222"))

16
codelogic

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

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'>
13
Rafe
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
Totoro
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')
9
Jerry T

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)
6
Nick

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
5
Sławomir Lenart

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

5
qwerty12345

Python a cette grande souplesse d’analyse dans un liners.

str = "545.2222"
print ("int: ", + int(float(a)))
print ("float: ", +(float(a)))
4
Harry_pb

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

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")
2
Khandelwal-manik

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.

1
SeasonalShot

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
0
Abhishek Bhatia

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'>
0
amirt