Comment analyser une chaîne en un flottant ou un int?

2253

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"en un entier 31,?

Je veux juste savoir comment analyser un flotteur str en un floatet (séparément) un int str en un int.

Tristan Havelick
la source
7
En règle générale, si vous avez un objet en Python et que vous souhaitez le convertir en ce type d'objet, faites appel type(my_object)à lui. Le résultat peut généralement être appelé en tant que fonction pour effectuer la conversion. Par exemple, les type(100)résultats en int, vous pouvez donc appeler int(my_object)pour essayer de convertir my_objecten un entier. Cela ne fonctionne pas toujours, mais c'est une bonne "première estimation" lors du codage.
robertlayton
1
int(x) if int(x) == float(x) else float(x)
tcpaiva

Réponses:

2628
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
Harley Holcombe
la source
8
je me demande juste pourquoi il y a '04' à la fin? pourquoi pas simplement '00'? aussi ma version actuelle de python n'a pas '04'.
Mangat Rai Modi
54
@MangatRaiModi Les nombres à virgule flottante sont intrinsèquement imparfaits pour représenter les décimales. Pour plus d'informations, voir stackoverflow.com/q/21895756/931277
dokkaebi
19
pourquoi pas simplement int(a)mais int(float(a))?
idclev 463035818
24
int(a)donnera une erreur indiquant que la chaîne n'est pas un entier valide:, ValueError: invalid literal for int() with base 10: '545.222'mais la conversion d'un flottant en un int est une conversion prise en charge.
David Parks
4
Vous devez gérer ValueErrorsi vous voulez être en sécurité
Joe Bobson
515
def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)
Javier
la source
81
le mélange implicite de flotteurs / entiers peut conduire à des bogues subtils en raison d'une possible perte de précision lors du travail avec des flotteurs ou à des résultats différents pour l' /opérateur sur les flotteurs / pouces. Selon le contexte, il peut être préférable de renvoyer int ou float, pas les deux.
jfs
14
@JFSebastian Vous avez tout à fait raison, mais il y a des moments où vous voulez que l'entrée dicte celle-là. Laisser l'entrée dicter laquelle peut fonctionner correctement avec la frappe de canard.
TimothyAWiseman
4
Vous pouvez en imbriquer une autre trypour lever une exception lorsqu'elle n'est pas convertible en flottant.
iBug
2
Échoue avecs = u'\u0000'
Matt Hancock
1
@iBug Bonne idée! Je recommande d' ValueErrorexcept
ajouter
511

Méthode Python pour vérifier si une chaîne est un flottant:

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 en 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 une grosse surprise.

N'utilisez pas ce code sur des logiciels vitaux!

Attraper de larges exceptions de cette façon, tuer les canaris et engloutir l'exception crée une toute petite chance qu'un flottant valide en tant que chaîne retourne faux. La float(...)ligne de code peut échouer pour mille raisons qui n'ont rien à voir avec le contenu de la chaîne. Mais si vous écrivez des logiciels vitaux dans un langage prototype de type canard comme Python, vous avez des problèmes beaucoup plus importants.

Eric Leschinski
la source
1
Si vrai devient 1, c'est que j'ai hérité du C ++ je pense
FindOutIslamNow
6
J'ai posté cette réponse en 2014. Ce UTF-8glyphe pour un chinois 4s'est transformé au fil des ans en fonction de la façon dont les développeurs stackoverflow modifient leur schéma de codage de caractères sur leur pile d'outils Microsoft. C'est une curiosité de le voir basculer au fil des ans alors que de nouveaux schémas de conversion affirment leurs nouvelles idéologies. Mais oui, tout UTF-8glyphe pour un numérique oriental oriental n'est pas un flotteur en Python. Bazinga.
Eric Leschinski
4
comment cela peut-il être si positivement voté, avec une si large exception?
E.Serra
Tout avec des espaces entre les deux ne peut pas être converti, comme "- 12.3"et"45 e6"
Simon
1
Cette clause d'exception devrait être limitée àTypeError, ValueError
wim
131

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 à partir de sources non fiables sans avoir besoin d'analyser les valeurs soi-même.

Autrement dit, un «eval» sûr

>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
wim
la source
11
ce n'est pas une bonne solution au problème. Cela fonctionne bien dans Python 2, mais ce qui suit se produit dans Python 3: python >>> import ast >>> ast.literal_eval('1-800-555-1212') -2566 >>> Pour clarifier pourquoi c'est un problème, si vous voulez laisser les numéros de téléphone seuls et ne pas supposer que ce sont des expressions mathématiques, cette approche n'est pas pour vous.
royce3
6
@ royce3 Oui, c'est un bon point et les utilisateurs doivent se méfier. Le comportement a été modifié à l'origine afin de résoudre certains problèmes liés à l'analyse de littéraux complexes. C'est sans doute un bug ast.literal_evalet a été discuté ici .
wim
79
float(x) if '.' in x else int(x)
Dino Viehland
la source
21
Remarque: soyez prudent lorsque vous traitez le montant d'argent passé sous forme de chaînes, car certains pays utilisent "," comme séparateurs décimaux
Ben G
127
@Emile: Je n'appellerais pas "2e-3" un "cas extrême". Cette réponse est juste cassée.
jchl
14
@BenG NE manipulez PAS l'argent comme un flottant. C'est demander des ennuis. Utilisez décimal pour de l'argent! (Mais votre commentaire sur ',' est toujours valable et important)
ToolmakerSteve
4
N'oubliez pas que "pas un nombre" (NaN) et +/- infini sont également des valeurs flottantes valides. Il en float("nan")est de même pour une valeur flottante parfaitement valide que la réponse ci-dessus n'attraperait pas du tout
Ronny Andersson
2
Facilement cassable par une adresse IP - 192.168.0.1; ou"This is not a good approach. :)"
Todor Minakov
69

Localisation et virgules

Vous devriez considérer la possibilité de virgules dans la représentation sous forme de chaîne d'un nombre, pour les cas comme celui float("545,545.2222")qui lève une exception. À la place, utilisez des méthodes dans localepour convertir les chaînes en nombres et interpréter correctement les virgules. La locale.atofméthode se transforme en un flottant en une seule é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 aux É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 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 - Conventions de numérotation européennes

Dans la majorité des pays du monde , les virgules sont utilisées pour les décimales au lieu des 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.atoiest également disponible, mais l'argument doit être un entier.

Mark Chackerian
la source
Cela semble être une solution idéale lorsque vous savez si un flottant ou un int doit être retourné, mais comment pouvez-vous obtenir ceci pour renvoyer un int uniquement si un int a été passé? Par exemple, x = '1'; locale.atof(x)retourne 1.0quand je veux réellement 1.
user5359531
En utilisant la méthode de Dino, je suppose que la réponse serait d'utiliser quelque chose comme ceci:locale.atof(x) if locale.localeconv().get('decimal_point') in x else locale.atoi(x)
user5359531
Je recommanderais d'utiliser la méthode de Javier ci-dessus (encapsulation locale.atoidans un essai et utilisation locale.atofsur exception - c'est probablement plus lisible.
Mark Chackerian
27

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
SethMMorton
la source
24

Les utilisateurs codelogic et harley sont corrects, mais gardez à l'esprit que si vous savez que la chaîne est un entier (par exemple, 545), vous pouvez appeler int ("545") sans lancer le premier casting pour flotter.

Si vos chaînes sont dans une liste, vous pouvez également utiliser la fonction de carte.

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

Peter Mortensen
la source
21

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" en un entier, 31? Je veux juste savoir comment analyser une chaîne flottante en flottant et (séparément) une chaîne int en un int.

Il est bon que vous demandiez de les faire séparément. Si vous les mélangez, vous pouvez vous préparer à des problèmes plus tard. La réponse simple est:

"545.2222" flotter:

>>> float("545.2222")
545.2222

"31" à un entier:

>>> int("31")
31

Autres conversions, entiers vers et depuis les chaînes et les littéraux:

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 savez qu'ils auront le bon préfixe, Python peut en déduire cela si vous passez 0comme 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 que votre propre code représente clairement des valeurs spécifiques codées en dur, cependant, vous n'aurez peut-être pas besoin de convertir à partir des bases - vous pouvez laisser Python le faire automatiquement pour vous avec la syntaxe correcte.

Vous pouvez utiliser les préfixes apropos pour obtenir la conversion automatique en 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 lors de la description des indicateurs binaires, des autorisations de fichier dans le code ou des valeurs hexadécimales pour les couleurs - par exemple, notez les 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 les octaux ambigus de Python 2 compatibles avec Python 3

Si vous voyez un entier qui commence par un 0, en Python 2, il s'agit de la syntaxe octale (obsolète).

>>> 037
31

C'est mauvais car il semble que 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 octaux qui fonctionnent à la fois en 2 et 3 avec le 0opréfixe:

>>> 0o37
31
Aaron Hall
la source
20

La question semble un peu ancienne. 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 ASCII donnée ne peut être convertie en aucune d'entre elles, elle la renvoie intacte. Le code peut bien sûr ê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'
krzym
la source
8
1e3est un nombre en python, mais une chaîne selon votre code.
Cees Timmerman
16

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

codelogic
la source
1
Cela vous donnera un objet flottant si votre chaîne se trouve être "0" ou "0.0", plutôt que l'int qu'elle donne pour d'autres nombres valides.
Brian
14

J'utilise cette fonction pour ça

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
Shameem
la source
Veuillez noter que parse_str(' 1')(avec un espace) reviendra None, non 1.
musiphil
13

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'>
Rafe
la source
11
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
Totoro
la source
1
Pourquoi voudriez-vous soulever dans votre exceptsection si vous ne faites rien là-bas? float () soulèverait pour vous.
Greg0ry
1
vous avez raison, je suppose que j'ai copié et collé à partir d'une fonctionnalité que je soulevais une exception particulière. va éditer. merci
Totoro
1
Cela va essayer d'analyser une chaîne et de retourner soit intou floatselon ce que la chaîne représente. Il peut augmenter les exceptions d'analyse ou [avoir un comportement inattendu] [1].
Kuzeko
9
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')
Jerry T
la source
6

Vous devez prendre en compte l'arrondi pour le faire correctement.

Ie int (5.1) => 5 int (5.6) => 5 - faux, devrait être 6 donc nous faisons int (5.6 + 0.5) => 6

def convert(n):
    try:
        return int(n)
    except ValueError:
        return float(n + 0.5)
pseudo
la source
4
Bon point. Cela provoque une inflation, cependant, Python 3 et d' autres langages modernes utilisent l'arrondi bancaire.
Cees Timmerman
2
Cette réponse est fausse (comme écrit à l'origine). Il embrouille les deux cas de intet float. Et cela donnera une exception, quand nest une chaîne, comme OP le souhaite. Peut - être que vous vouliez dire: Quand un intrésultat souhaité, rounddevrait être fait conversion AFTER flotter. Si la fonction doit TOUJOURS retourner un entier, alors vous n'avez pas besoin de la partie except - le corps entier de la fonction peut l'être int(round(float(input))). Si la fonction doit retourner un int si possible, sinon un flottant, alors la solution originale de javier est correcte!
ToolmakerSteve
5

Je suis surpris que personne ne mentionne l'expression régulière car parfois la chaîne doit être préparée et normalisée avant de lancer le 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
Sławomir Lenart
la source
5

Pour transtyper en python, utilisez les fonctions constructeur du type, en passant la chaîne (ou la valeur que vous essayez de caster) comme paramètre.

Par exemple:

>>>float("23.333")
   23.333

Dans les coulisses, python appelle la __float__méthode des objets , 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 __float__méthode afin qu'il puisse être converti en un float en utilisant float (myobject).

kCODINGeroo
la source
3

Il s'agit d'une version corrigée de https://stackoverflow.com/a/33017514/5973334

Cela va essayer d'analyser une chaîne et de retourner soit intou floatselon ce que la chaîne représente. Il peut augmenter les exceptions d'analyse ou avoir 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
Kuzeko
la source
2

Passez votre chaîne à cette fonction:

def string_to_number(str):
  if("." in str):
    try:
      res = float(str)
    except:
      res = str  
  elif(str.isdigit()):
    res = int(str)
  else:
    res = str
  return(res)

Il renverra int, float ou string selon ce qui a été passé.

chaîne qui est un int

print(type(string_to_number("124")))
<class 'int'>

chaîne qui est un flotteur

print(type(string_to_number("12.4")))
<class 'float'>

chaîne qui est une chaîne

print(type(string_to_number("hello")))
<class 'str'>

chaîne qui ressemble à un flotteur

print(type(string_to_number("hel.lo")))
<class 'str'>
Cybernétique
la source
1

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 façon la plus Pythonique que j'ai pu trouver.

Saisonnier
la source
Le générateur s'arrête après la première interprétation de float. Le bloc trycatchdevrait probablement être à l'intérieur de la forboucle.
musiphil
1

Gère hex, octal, binaire, décimal et flottant

Cette solution gérera toutes les conventions de chaîne pour les nombres (tout ce que je sais).

def to_number(n):
    ''' Convert any number representation to a number 
    This covers: float, decimal, hex, and octal numbers.
    '''

    try:
        return int(str(n), 0)
    except:
        try:
            # python 3 doesn't accept "010" as a valid octal.  You must use the
            # '0o' prefix
            return int('0o' + n, 0)
        except:
            return float(n)

Cette sortie de scénario de test illustre ce dont je parle.

======================== CAPTURED OUTPUT =========================
to_number(3735928559)   = 3735928559 == 3735928559
to_number("0xFEEDFACE") = 4277009102 == 4277009102
to_number("0x0")        =          0 ==          0
to_number(100)          =        100 ==        100
to_number("42")         =         42 ==         42
to_number(8)            =          8 ==          8
to_number("0o20")       =         16 ==         16
to_number("020")        =         16 ==         16
to_number(3.14)         =       3.14 ==       3.14
to_number("2.72")       =       2.72 ==       2.72
to_number("1e3")        =     1000.0 ==       1000
to_number(0.001)        =      0.001 ==      0.001
to_number("0xA")        =         10 ==         10
to_number("012")        =         10 ==         10
to_number("0o12")       =         10 ==         10
to_number("0b01010")    =         10 ==         10
to_number("10")         =         10 ==         10
to_number("10.0")       =       10.0 ==         10
to_number("1e1")        =       10.0 ==         10

Voici le test:

class test_to_number(unittest.TestCase):

    def test_hex(self):
        # All of the following should be converted to an integer
        #
        values = [

                 #          HEX
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (0xDEADBEEF  , 3735928559), # Hex
                ("0xFEEDFACE", 4277009102), # Hex
                ("0x0"       ,          0), # Hex

                 #        Decimals
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (100         ,        100), # Decimal
                ("42"        ,         42), # Decimal
            ]



        values += [
                 #        Octals
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (0o10        ,          8), # Octal
                ("0o20"      ,         16), # Octal
                ("020"       ,         16), # Octal
            ]


        values += [
                 #        Floats
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (3.14        ,       3.14), # Float
                ("2.72"      ,       2.72), # Float
                ("1e3"       ,       1000), # Float
                (1e-3        ,      0.001), # Float
            ]

        values += [
                 #        All ints
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                ("0xA"       ,         10), 
                ("012"       ,         10), 
                ("0o12"      ,         10), 
                ("0b01010"   ,         10), 
                ("10"        ,         10), 
                ("10.0"      ,         10), 
                ("1e1"       ,         10), 
            ]

        for _input, expected in values:
            value = to_number(_input)

            if isinstance(_input, str):
                cmd = 'to_number("{}")'.format(_input)
            else:
                cmd = 'to_number({})'.format(_input)

            print("{:23} = {:10} == {:10}".format(cmd, value, expected))
            self.assertEqual(value, expected)
musaraigne
la source
0

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'>
Peter Mortensen
la source
0

Il s'agit d'une fonction qui convertira tout object(et pas seulement str) en intou float, selon que la chaîne réelle fournie ressemble à int ou float. De plus, si c'est un objet qui a les deux méthodes __floatet __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
Abhishek Bhatia
la source
-1

En utilisant les méthodes int et float, nous pouvons convertir une chaîne en entier et en flottant.

s="45.8"
print(float(s))

y='67'
print(int(y))
Shekku Joseph
la source
Cette réponse n'ajoute rien de nouveau. Voir, par exemple, cette réponse qui donne les mêmes informations et plus encore.
Georgy
-3

eval()est une très bonne solution à cette question. Il n'a pas besoin de vérifier si le nombre est entier ou flottant, il donne juste l'équivalent correspondant. Si d'autres méthodes sont requises, essayez

if '.' in string:
    print(float(string))
else:
    print(int(string))

try-except peut également être utilisé comme alternative. Essayez de convertir la chaîne en int dans le bloc try. Si la chaîne est une valeur flottante, elle générera une erreur qui sera interceptée dans le bloc except, comme ceci

try:
    print(int(string))
except:
    print(float(string))
Swati Srivastava
la source
-10

Voici une autre interprétation de votre question (indice: c'est vague). Il est possible que vous recherchiez quelque chose comme ceci:

def parseIntOrFloat( aString ):
    return eval( aString )

Cela fonctionne comme ça ...

>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545

Théoriquement, il existe une vulnérabilité d'injection. La chaîne pourrait, par exemple, être "import os; os.abort()". Sans aucun contexte sur la provenance de la chaîne, cependant, la possibilité est une spéculation théorique. La question étant vague, il n'est pas du tout clair si cette vulnérabilité existe réellement ou non.

S.Lott
la source
7
Même si son entrée est sûre à 100%, elle eval()est plus de 3 fois plus lente que try: int(s) except: float(s).
Cees Timmerman
1
Eh bien, evalc'est une mauvaise pratique (vous devez le savoir parce que vous avez une réputation de 310k)
U10-Forward