301 votes

Vérifier si une chaîne de caractères peut être convertie en float en Python

J'ai un peu de code Python qui s'exécute par le biais d'une liste de chaînes de caractères et les convertit en nombres entiers ou des nombres à virgule flottante, si possible. Faire cela pour les entiers est assez facile

if element.isdigit():
    newelement=int(element)

Les nombres à virgule flottante sont les plus difficiles. Je suis aujourd'hui l'utilisation de la partition('.') pour fractionner la chaîne et de la vérification pour s'assurer que l'un ou les deux côtés sont des chiffres.

partition=element.partition('.')
if (partition[0].isdigit() and partition[1]=='.' and partition[2].isdigit()) or (partition[0]=='' and partition[1]=='.' and partition[2].isdigit()) or (partition[0].isdigit() and partition[1]=='.' and partition[2]==''):
    newelement=float(element)

Cela fonctionne, mais, évidemment, si l'instruction est un peu un ours. L'autre solution que j'ai envisagé de juste envelopper la conversion dans un bloc try/catch et de voir si elle réussit, comme décrit dans cette question.

Quelqu'un a d'autres idées? Avis sur les mérites relatifs de la partition et try/catch approches?

433voto

dbr Points 66401

Je voudrais juste utiliser..

try:
    float(element)
except ValueError:
    print "Not a float"

..c'est simple, et ça fonctionne

Une autre option serait une expression régulière:

import re
if re.match("^\d+?\.\d+?$", element) is None:
    print "Not float"

312voto

Eric Leschinski Points 14289

Python méthode pour vérifier float:

def isfloat(value):
  try:
    float(value)
    return True
  except ValueError:
    return False

Ne pas obtenir un peu par les gobelins se cachant dans le flotteur bateau! FAIRE LES TESTS UNITAIRES!

Ce qui est, et n'est pas un float peut-être vous surprendre:

Command to parse                        Is it a float?  Comment
--------------------------------------  --------------- ------------
print(isfloat(""))                      False
print(isfloat("1234567"))               True 
print(isfloat("NaN"))                   True            nan is also float
print(isfloat("NaNananana BATMAN"))     False
print(isfloat("123.456"))               True
print(isfloat("123.E4"))                True
print(isfloat(".1"))                    True
print(isfloat("1,234"))                 False
print(isfloat("NULL"))                  False           case insensitive
print(isfloat(",1"))                    False           
print(isfloat("123.EE4"))               False           
print(isfloat("6.523537535629999e-07")) True
print(isfloat("6e777777"))              True            This is same as Inf
print(isfloat("-iNF"))                  True
print(isfloat("1.797693e+308"))         True
print(isfloat("infinity"))              True
print(isfloat("infinity and BEYOND"))   False
print(isfloat("12.34.56"))              False           Two dots not allowed.
print(isfloat("#56"))                   False
print(isfloat("56%"))                   False
print(isfloat("0E0"))                   True
print(isfloat("x86E0"))                 False
print(isfloat("86-5"))                  False
print(isfloat("True"))                  False           Boolean is not float.   
print(isfloat("-5e-5"))                 True
print(isfloat("+1e1^5"))                False
print(isfloat("+1e1"))                  True
print(isfloat("+1e1.3"))                False
print(isfloat("+1.3P1"))                False
print(isfloat("-+1"))                   False
print(isfloat("(1)"))                   False           brackets not interpreted

7voto

Jacob Gabrielson Points 8800

Si vous vous souciez de la performance (et je ne dis pas que vous devriez le savoir), l'essai de l'approche fondée sur le gagnant clair (par rapport avec votre partition de base de l'approche ou de la regexp approche), aussi longtemps que vous ne vous attendez pas beaucoup de chaînes non valides, dans ce cas, c'est potentiellement plus (sans doute à cause du coût de la gestion des exceptions).

Encore une fois, je ne dis pas que vous vous souciez de la performance, tout en vous donnant les données dans le cas où vous êtes en train de faire ce 10 milliards de fois par seconde, ou quelque chose. Aussi, la partition à base de code ne gère pas au moins une chaîne valide.

$ ./floatstr.py
F..
partition triste: 3.1102449894
partition heureux: 2.09208488464
..
re triste: 7.76906108856
re: heureux: 7.09421992302
..
essayez triste: 12.1525540352
essayez heureux: 1.44165301323
.
======================================================================
FAIL: test_partition (__principaux__.ConvertTests)
----------------------------------------------------------------------
Traceback (most recent call last):
 Le fichier "./floatstr.py", ligne 48, dans test_partition
auto.failUnless(is_float_partition("20e2"))
AssertionError

----------------------------------------------------------------------
Couru 8 tests dans 33.670 s

FAILED (échec=1)

Voici le code (Python 2.6, regexp prises de Jean Gietzen de la réponse):

def is_float_try(str):
    try:
        float(str)
        return True
    except ValueError:
        return False

import re
_float_regexp = re.compile(r"^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$")
def is_float_re(str):
    return re.match(_float_regexp, str)


def is_float_partition(element):
    partition=element.partition('.')
    if (partition[0].isdigit() and partition[1]=='.' and partition[2].isdigit()) or (partition[0]=='' and partition[1]=='.' and pa\
rtition[2].isdigit()) or (partition[0].isdigit() and partition[1]=='.' and partition[2]==''):
        return True

if __name__ == '__main__':
    import unittest
    import timeit

    class ConvertTests(unittest.TestCase):
        def test_re(self):
            self.failUnless(is_float_re("20e2"))

        def test_try(self):
            self.failUnless(is_float_try("20e2"))

        def test_re_perf(self):
            print
            print 're sad:', timeit.Timer('floatstr.is_float_re("12.2x")', "import floatstr").timeit()
            print 're happy:', timeit.Timer('floatstr.is_float_re("12.2")', "import floatstr").timeit()

        def test_try_perf(self):
            print
            print 'try sad:', timeit.Timer('floatstr.is_float_try("12.2x")', "import floatstr").timeit()
            print 'try happy:', timeit.Timer('floatstr.is_float_try("12.2")', "import floatstr").timeit()

        def test_partition_perf(self):
            print
            print 'partition sad:', timeit.Timer('floatstr.is_float_partition("12.2x")', "import floatstr").timeit()
            print 'partition happy:', timeit.Timer('floatstr.is_float_partition("12.2")', "import floatstr").timeit()

        def test_partition(self):
            self.failUnless(is_float_partition("20e2"))

        def test_partition2(self):
            self.failUnless(is_float_partition(".2"))

        def test_partition3(self):
            self.failIf(is_float_partition("1234x.2"))

    unittest.main()

3voto

John Gietzen Points 23645

Cette regex vérifie scientifique des nombres à virgule flottante:

^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$

Cependant, je crois que votre meilleur pari est d'utiliser l'analyseur dans un essai.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X