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.

Était-ce utile?

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

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top