Comment vérifier si une chaîne est un nombre (float)?

Quelle est la meilleure façon de vérifier si une chaîne peut être représentée sous forme de nombre en Python?

la fonction que j'ai actuellement est:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

qui, non seulement est laid et lent, semble grotesque. Cependant, je n'ai pas trouvé de meilleure méthode car appeler float dans la fonction principale est encore pire.

1282
demandé sur martineau 2008-12-09 23:03:42

30 réponses

qui, non seulement est laid et lent

Je contesterais les deux.

une analyse regex ou une autre chaîne de caractères serait plus laide et plus lente.

Je ne suis pas sûr que beaucoup puisse être plus rapide que ce qui précède. Il appelle la fonction et retourne. Try / Catch n'introduit pas beaucoup de overhead parce que l'exception la plus commune est capturée sans une recherche extensive des cadres de pile.

Le problème est que toute fonction de conversion numérique a deux types de résultats

  • Un numéro si le numéro est valide
  • un code d'état (par exemple, via errno) ou une exception pour montrer qu'aucun numéro valide ne pouvait être interprété.

C (à titre d'exemple) pirate ce un certain nombre de façons. Python pose clairement et explicitement.

je pense que votre code pour faire ça est parfait.

579
répondu S.Lott 2013-05-21 18:02:21

dans le cas où vous recherchez parsing (positif, non signé) des entiers au lieu de flotteurs, vous pouvez utiliser la fonction isdigit() pour les objets string.

>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False

Méthodes String - isdigit()

il y a aussi quelque chose sur les chaînes Unicode, que je ne connais pas très bien. Unicode Est décimal/decimal

1366
répondu Zoomulator 2016-04-22 09:20:10

TL; DR la meilleure solution est s.replace('.','',1).isdigit()

"

j'ai fait quelques repères la comparaison des différentes approches

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

import re    
def is_number_regex(s):
    """ Returns True is string is a number. """
    if re.match("^\d+?\.\d+?$", s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()

si la chaîne n'est pas un nombre, le bloc excepté est assez lent. Mais plus important encore, la méthode try-except est la seule approche qui traite correctement les notations scientifiques.

funcs = [
          is_number_tryexcept, 
          is_number_regex,
          is_number_repl_isdigit
          ]

a_float = '.1234'

print('Float notation ".1234" is not supported by:')
for f in funcs:
    if not f(a_float):
        print('\t -', f.__name__)

Float notation".1234" n'est pas supporté par:

- is_number_regex

scientific1 = '1.000000e+50'
scientific2 = '1e50'


print('Scientific notation "1.000000e+50" is not supported by:')
for f in funcs:
    if not f(scientific1):
        print('\t -', f.__name__)




print('Scientific notation "1e50" is not supported by:')
for f in funcs:
    if not f(scientific2):
        print('\t -', f.__name__)

notation Scientifique "1.000000 e+50" n'est pas pris en charge par:

- is_number_regex

- is_number_repl_isdigit

La notation scientifique "1e50" n'est pas supportée par:

- is_number_regex

- is_number_repl_isdigit

EDIT: les résultats de référence

import timeit

test_cases = ['1.12345', '1.12.345', 'abc12345', '12345']
times_n = {f.__name__:[] for f in funcs}

for t in test_cases:
    for f in funcs:
        f = f.__name__
        times_n[f].append(min(timeit.Timer('%s(t)' %f, 
                      'from __main__ import %s, t' %f)
                              .repeat(repeat=3, number=1000000)))

où les fonctions suivantes ont été testées

from re import match as re_match
from re import compile as re_compile

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

def is_number_regex(s):
    """ Returns True is string is a number. """
    if re_match("^\d+?\.\d+?$", s) is None:
        return s.isdigit()
    return True


comp = re_compile("^\d+?\.\d+?$")    

def compiled_regex(s):
    """ Returns True is string is a number. """
    if comp.match(s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()

enter image description here

72
répondu Sebastian 2017-07-12 23:39:00

il y a une exception que vous pouvez prendre en compte: la chaîne "nan "

si vous voulez que IS_NUMBER retourne FALSE pour 'NaN' ce code ne fonctionnera pas car Python le convertit à sa représentation d'un nombre qui n'est pas un nombre (parlez des problèmes d'identité):

>>> float('NaN')
nan

sinon, je devrais vous remercier pour le morceau de code que j'utilise maintenant largement. :)

G.

64
répondu gvrocha 2010-09-01 14:06:08

que pensez-vous de ceci:

'3.14'.replace('.','',1).isdigit()

qui ne retournera vrai que s'il y en a un ou pas.""dans la chaîne de chiffres.

'3.14.5'.replace('.','',1).isdigit()

retournera false

edit: viens de voir un autre commentaire ... ajouter un .replace(badstuff,'',maxnum_badstuff) pour les autres cas peut être fait. si vous passez du sel et non des condiments arbitraires (réf: xkcd#974 ) cela fera très bien: p

52
répondu haxwithaxe 2013-05-21 17:58:07

mis à jour après que Alfe a souligné que vous n'avez pas besoin de vérifier pour flotteur séparément comme les poignées complexes à la fois:

def is_number(s):
    try:
        complex(s) # for int, long, float and complex
    except ValueError:
        return False

    return True

précédemment dit: Est-ce que certains cas rares, vous pourriez aussi avoir besoin de vérifier des nombres complexes( par exemple 1+2i), qui ne peuvent pas être représentés par un flotteur:

def is_number(s):
    try:
        float(s) # for int, long and float
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False

    return True
38
répondu Matthew Wilcoxson 2016-04-22 15:42:05

qui, non seulement est laid et lent, semble grotesque.

cela peut prendre un peu de s'habituer, mais c'est la façon pythonique de le faire. Comme on l'a déjà souligné, les alternatives sont pires. Mais il y a un autre avantage à faire les choses de cette façon: le polymorphisme.

L'idée centrale de duck-typing est que "si ça marche et parle comme un canard, alors c'est un canard."Que faire si vous décidez que vous avez besoin de sous-classe chaîne de chaîne de sorte que vous pouvez changer comment vous déterminez si quelque chose peut être converti en un flotteur? Ou si vous décidez de tester un autre objet entièrement? Vous pouvez faire ces choses sans avoir à changer le code ci-dessus.

d'autres langues résolvent ces problèmes en utilisant des interfaces. Je garde l'analyse de la solution qui est meilleure pour un autre fil. Le point, cependant, est que python est décidément sur le côté canard Dactylographie de l'équation, et vous allez probablement devoir s'habituer à une syntaxe comme celle-ci si vous prévoyez de faire beaucoup de programmation en Python (mais cela ne veut pas dire que vous devez l'aimer bien sûr).

une autre chose que vous pourriez vouloir prendre en considération: Python est assez rapide dans le lancement et la capture d'exceptions par rapport à beaucoup d'autres langues (30x plus rapide que .Net par exemple). Zut, le langage lui-même jette même des exceptions pour communiquer non-exceptionnel, conditions normales de programme (chaque fois que vous utilisez un pour boucle.) Ainsi, Je ne m'inquiéterais pas trop des aspects de performance de ce code jusqu'à ce que vous remarquiez un problème important.

37
répondu Jason Baker 2008-12-11 04:56:26

pour int utilisez ceci:

>>> "1221323".isdigit()
True

Mais pour float nous avons besoin de quelques trucs ;-). Chaque numéro de flotteur a un point...

>>> "12.34".isdigit()
False
>>> "12.34".replace('.','',1).isdigit()
True
>>> "12.3.4".replace('.','',1).isdigit()
False

pour les nombres négatifs, il suffit d'ajouter lstrip() :

>>> '-12'.lstrip('-')
'12'

Et maintenant, nous obtenons un moyen universel:

>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False
18
répondu Sdwdaw 2015-09-08 08:42:14

pour les chaînes de non-nombres, try: except: est en fait plus lent que les expressions régulières. Pour les chaînes de nombres valides, regex est plus lent. Donc, la méthode appropriée dépend de votre entrée.

si vous trouvez que vous êtes dans une performance bind, vous pouvez utiliser un nouveau module tiers appelé fastnumbers qui fournit une fonction appelée isfloat . La divulgation complète, je suis l'auteur. J'ai inclus ses résultats dans le temps ci-dessous.


from __future__ import print_function
import timeit

prep_base = '''\
x = 'invalid'
y = '5402'
z = '4.754e3'
'''

prep_try_method = '''\
def is_number_try(val):
    try:
        float(val)
        return True
    except ValueError:
        return False

'''

prep_re_method = '''\
import re
float_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').match
def is_number_re(val):
    return bool(float_match(val))

'''

fn_method = '''\
from fastnumbers import isfloat

'''

print('Try with non-number strings', timeit.timeit('is_number_try(x)',
    prep_base + prep_try_method), 'seconds')
print('Try with integer strings', timeit.timeit('is_number_try(y)',
    prep_base + prep_try_method), 'seconds')
print('Try with float strings', timeit.timeit('is_number_try(z)',
    prep_base + prep_try_method), 'seconds')
print()
print('Regex with non-number strings', timeit.timeit('is_number_re(x)',
    prep_base + prep_re_method), 'seconds')
print('Regex with integer strings', timeit.timeit('is_number_re(y)',
    prep_base + prep_re_method), 'seconds')
print('Regex with float strings', timeit.timeit('is_number_re(z)',
    prep_base + prep_re_method), 'seconds')
print()
print('fastnumbers with non-number strings', timeit.timeit('isfloat(x)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with integer strings', timeit.timeit('isfloat(y)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with float strings', timeit.timeit('isfloat(z)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print()

Try with non-number strings 2.39108395576 seconds
Try with integer strings 0.375686168671 seconds
Try with float strings 0.369210958481 seconds

Regex with non-number strings 0.748660802841 seconds
Regex with integer strings 1.02021503448 seconds
Regex with float strings 1.08564686775 seconds

fastnumbers with non-number strings 0.174362897873 seconds
fastnumbers with integer strings 0.179651021957 seconds
fastnumbers with float strings 0.20222902298 seconds

comme vous pouvez voir

  • try: except: était rapide pour une entrée numérique mais très lent pour une entrée invalide
  • regex est très efficace lorsque l'entrée n'est pas valide
  • fastnumbers gagne dans les deux cas,
15
répondu SethMMorton 2017-08-20 02:49:02

Seulement Imiter C#

dans C# il y a deux fonctions différentes qui gèrent l'analyse des valeurs scalaires:

  • Float.Parse ()
  • flotteur.TryParse ()

float.parse ():

def parse(string):
    try:
        return float(string)
    except Exception:
        throw TypeError

Note: Si vous vous demandez pourquoi j'ai changé l'exception à une erreur de frappe, voici le documentation .

float.try_parse ():

def try_parse(string, fail=None):
    try:
        return float(string)
    except Exception:
        return fail;

Note: Vous ne voulez pas retourner le booléen 'False' parce que c'est toujours un type de valeur. Aucun n'est meilleur parce qu'il indique l'échec. Bien sûr, si vous voulez quelque chose de différent, vous pouvez modifier l'échec de paramètre que vous voulez.

pour étendre le flotteur pour inclure le "parse ()" et 'try_parse () 'vous aurez besoin de la classe' float ' pour ajouter ces méthodes.

si vous voulez respecter les fonctions préexistantes, le code devrait ressembler à quelque chose comme:

def monkey_patch():
    if(!hasattr(float, 'parse')):
        float.parse = parse
    if(!hasattr(float, 'try_parse')):
        float.try_parse = try_parse

SideNote: personnellement, je préfère l'appeler Monkey Punching parce qu'il se sent comme j'abuse de la langue quand je fais ceci mais YMMV.

Utilisation:

float.parse('giggity') // throws TypeException
float.parse('54.3') // returns the scalar value 54.3
float.tryParse('twank') // returns None
float.tryParse('32.2') // returns the scalar value 32.2

et le grand sauge Pythonas a dit au Saint-Siège Sharpisus," Tout ce que vous pouvez faire je peux faire mieux; je peux faire tout mieux que vous."

14
répondu Evan Plaice 2012-02-18 01:40:36

je sais que c'est particulièrement ancien, mais je voudrais ajouter une réponse je crois couvre l'information manquante de la plus haute réponse votée qui pourrait être très utile à tous ceux qui trouvent cela:

Pour chacune des méthodes suivantes connecter avec un compte si vous avez besoin d'une entrée pour être accepté. (En supposant que nous utilisons des définitions vocales d'entiers plutôt que 0-255, etc.)

x.isdigit() fonctionne bien pour vérifier si x est un entier.

x.replace('-','').isdigit() fonctionne bien pour vérifier si x est négatif.(Arrivée en première position)

x.replace('.','').isdigit() fonctionne bien pour vérifier si x est un nombre décimal.

x.replace(':','').isdigit() fonctionne bien pour vérifier si x est un rapport.

x.replace('/','',1).isdigit() fonctionne bien pour vérifier si x est une fraction.

12
répondu Aruthawolf 2017-04-12 16:43:01

Coulée flotter et attraper ValueError est probablement le moyen le plus rapide, depuis float() est spécifiquement conçu pour cela. Tout ce qui nécessite l'analyse de chaîne (regex, etc) sera probablement plus lent en raison du fait qu'il n'est pas accordé pour cette opération. Mon de 0,02$.

10
répondu codelogic 2008-12-09 20:31:49

vous pouvez utiliser des chaînes Unicode, ils ont une méthode pour faire exactement ce que vous voulez:

>>> s = u"345"
>>> s.isnumeric()
True

ou:

>>> s = "345"
>>> u = unicode(s)
>>> u.isnumeric()
True

http://www.tutorialspoint.com/python/string_isnumeric.htm

http://docs.python.org/2/howto/unicode.html

10
répondu Blackzafiro 2013-03-04 16:12:38

je voulais voir quelle méthode est la plus rapide. Dans l'ensemble, la fonction check_replace a donné les meilleurs résultats et les plus constants. Les résultats les plus rapides ont été donnés par la fonction check_exception , mais seulement s'il n'y avait pas d'exception tirée - ce qui signifie que son code est le plus efficace, mais la hauteur de lancer une exception est assez grande.

s'il Vous Plaît noter que la vérification d'une coulée réussie est la seule méthode qui est précise, par exemple, cela fonctionne avec check_exception mais les deux autres fonctions d'essai retourneront False pour un flotteur valide:

huge_number = float('1e+100')

voici le code de référence:

import time, re, random, string

ITERATIONS = 10000000

class Timer:    
    def __enter__(self):
        self.start = time.clock()
        return self
    def __exit__(self, *args):
        self.end = time.clock()
        self.interval = self.end - self.start

def check_regexp(x):
    return re.compile("^\d*\.?\d*$").match(x) is not None

def check_replace(x):
    return x.replace('.','',1).isdigit()

def check_exception(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

to_check = [check_regexp, check_replace, check_exception]

print('preparing data...')
good_numbers = [
    str(random.random() / random.random()) 
    for x in range(ITERATIONS)]

bad_numbers = ['.' + x for x in good_numbers]

strings = [
    ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(1,10)))
    for x in range(ITERATIONS)]

print('running test...')
for func in to_check:
    with Timer() as t:
        for x in good_numbers:
            res = func(x)
    print('%s with good floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in bad_numbers:
            res = func(x)
    print('%s with bad floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in strings:
            res = func(x)
    print('%s with strings: %s' % (func.__name__, t.interval))

Voici les résultats avec Python 2.7.10 sur un MacBook Pro 13 2017:

check_regexp with good floats: 12.688639
check_regexp with bad floats: 11.624862
check_regexp with strings: 11.349414
check_replace with good floats: 4.419841
check_replace with bad floats: 4.294909
check_replace with strings: 4.086358
check_exception with good floats: 3.276668
check_exception with bad floats: 13.843092
check_exception with strings: 15.786169

Voici les résultats avec Python 3.6.5 sur un MacBook Pro 13 2017:

check_regexp with good floats: 13.472906000000009
check_regexp with bad floats: 12.977665000000016
check_regexp with strings: 12.417542999999995
check_replace with good floats: 6.011045999999993
check_replace with bad floats: 4.849356
check_replace with strings: 4.282754000000011
check_exception with good floats: 6.039081999999979
check_exception with bad floats: 9.322753000000006
check_exception with strings: 9.952595000000002

Voici les résultats avec PyPy 2.7.13 sur un 2017 MacBook Pro 13:

check_regexp with good floats: 2.693217
check_regexp with bad floats: 2.744819
check_regexp with strings: 2.532414
check_replace with good floats: 0.604367
check_replace with bad floats: 0.538169
check_replace with strings: 0.598664
check_exception with good floats: 1.944103
check_exception with bad floats: 2.449182
check_exception with strings: 2.200056
8
répondu Ron Reiter 2018-04-28 15:25:04

disons que vous avez des chiffres dans la chaîne. str = " 100949" et vous aimeriez vérifier si elle a seulement des numéros

if str.isdigit():
returns TRUE or FALSE 

isdigit docs

sinon votre méthode fonctionne très bien pour trouver l'occurrence d'un caractère dans une chaîne.

7
répondu Clayton 2014-10-13 09:17:53

cette réponse fournit un guide étape par étape ayant une fonction avec des exemples pour trouver la chaîne est:

  • entier Positif
  • Positif/négatif - entier/flottant
  • Comment supprimer les chaînes " NaN " (pas un nombre) lors de la vérification du nombre?

vérifier si la chaîne est positif entier

vous pouvez utiliser str.isdigit() pour vérifier si une chaîne de caractères donnée est positif entier.

Résultats De L'Échantillon:

# For digit
>>> '1'.isdigit()
True
>>> '1'.isalpha()
False

Vérifier la chaîne de positif/négatif entier/flottant

str.isdigit() renvoie False si la chaîne est un négatif nombre ou un float nombre. Par exemple:

# returns `False` for float
>>> '123.3'.isdigit()
False
# returns `False` for negative number
>>> '-123'.isdigit()
False

si vous voulez cochez également la case négatif entiers et float , ensuite, vous pouvez écrire une fonction personnalisée pour vérifier qu'il est:

def is_number(n):
    try:
        float(n)   # Type-casting the string to `float`.
                   # If string is not a valid `float`, 
                   # it'll raise `ValueError` exception
    except ValueError:
        return False
    return True

Exemple:

>>> is_number('123')    # positive integer number
True

>>> is_number('123.4')  # positive float number
True

>>> is_number('-123')   # negative integer number
True

>>> is_number('-123.4') # negative `float` number
True

>>> is_number('abc')    # `False` for "some random" string
False

jeter " NAN "(pas un nombre) chaînes lors de la vérification du nombre

les fonctions ci-dessus seront return True pour la chaîne" NAN " (Not a number) car pour Python il est valide float représentant il n'est pas un nombre. Par exemple:

>>> is_number('NaN')
True

afin de vérifier si le nombre est "NaN", vous pouvez utiliser math.isnan() comme:

>>> import math
>>> nan_num = float('nan')

>>> math.isnan(nan_num)
True

ou si vous ne voulez pas importer de bibliothèque supplémentaire pour vérifier cela, alors vous pouvez simplement le vérifier en le comparant avec lui-même en utilisant == . Python renvoie False quand nan est comparé avec lui-même. Par exemple:

# `nan_num` variable is taken from above example
>>> nan_num == nan_num
False

donc, au-dessus de fonction is_number peut être mis à jour pour retourner False pour "NaN" comme:

def is_number(n):
    is_number = True
    try:
        num = float(n)
        # check for "nan" floats
        is_number = num == num   # or use `math.isnan(num)`
    except ValueError:
        is_number = False
    return is_number

Exemple:

>>> is_number('Nan')   # not a number "Nan" string
False

>>> is_number('nan')   # not a number string "nan" with all lower cased
False

>>> is_number('123')   # positive integer
True

>>> is_number('-123')  # negative integer
True

>>> is_number('-1.12') # negative `float`
True

>>> is_number('abc')   # "some random" string
False

PS: chaque opération pour chaque contrôle en fonction du type de nombre vient avec supplémentaire généraux. Choisissez la version de la fonction is_number qui correspond à vos besoins.

7
répondu Moinuddin Quadri 2018-02-16 10:17:39

donc pour le mettre ensemble, en vérifiant pour Nan, infini et nombres complexes (il semblerait qu'ils sont spécifiés avec j, pas i, i.e. 1+2j) il résulte en:

def is_number(s):
    try:
        n=str(float(s))
        if n == "nan" or n=="inf" or n=="-inf" : return False
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False
    return True
6
répondu a1an 2012-03-23 16:10:09

votre code me semble correct.

peut-être pensez-vous que le code est "clunky" à cause de l'utilisation d'exceptions? Notez que les programmeurs Python ont tendance à utiliser les exceptions de façon libérale quand cela améliore la lisibilité du code, grâce à sa faible performance pénalité.

5
répondu Dubhead 2008-12-11 04:03:03

j'ai fait un test de vitesse. Disons que si la chaîne de caractères est probable pour être un numéro, la stratégie try/except est la plus rapide possible.Si la chaîne est pas susceptible d'être un nombre et vous êtes intéressé par entier vérifier, il vaut la peine de faire un certain test (isdigit plus heading '-'). Si vous êtes intéressé à vérifier le nombre de flotteurs, vous devez utiliser le essayer / sauf code sans s'échapper.

4
répondu FxIII 2010-10-12 07:43:19

je devais déterminer si une corde moulée dans les types de base (float,int,str,bool). Après n'avoir rien trouvé sur internet, j'ai créé ceci:

def str_to_type (s):
    """ Get possible cast type for a string

    Parameters
    ----------
    s : string

    Returns
    -------
    float,int,str,bool : type
        Depending on what it can be cast to

    """    
    try:                
        f = float(s)        
        if "." not in s:
            return int
        return float
    except ValueError:
        value = s.upper()
        if value == "TRUE" or value == "FALSE":
            return bool
        return type(s)

exemple

str_to_type("true") # bool
str_to_type("6.0") # float
str_to_type("6") # int
str_to_type("6abc") # str
str_to_type(u"6abc") # unicode       

, Vous pouvez capturer le type et l'utiliser

s = "6.0"
type_ = str_to_type(s) # float
f = type_(s) 
4
répondu astrodsg 2014-07-03 17:12:27

suggère RyanN

si vous voulez retourner False pour un NaN et Inf, changez la ligne en x = float(s); return (x == x) et (x - 1 != x). Cela devrait être vrai pour tous les flotteurs sauf Inf et NaN

mais cela ne fonctionne pas tout à fait, parce que pour des flotteurs suffisamment grands, x-1 == x retourne vrai. Par exemple, 2.0**54 - 1 == 2.0**54

3
répondu philh 2014-06-25 17:33:31

l'entrée peut être la suivante:

a="50" b=50 c=50.1 d="50.1"


1-Entrée générale:

L'entrée de cette fonction peut être tout!

trouve si la variable donnée est numérique. Les chaînes numériques se composent du signe optionnel, de n'importe quel nombre de chiffres, de la partie décimale optionnelle et de la partie exponentielle optionnelle. + 0123.45e6 est une valeur numérique valide. La notation hexadécimale (par exemple 0xf4c3b00c) et binaire (par exemple 0b10100111001) n'est pas autorisée.

is_numeric fonction

import ast
import number
def is_numeric(obj):
    if isinstance(obj, numbers.Number):
        return True
    elif isinstance(obj, str):
        nodes = list(ast.walk(ast.parse(obj)))[1:]
        if not isinstance(nodes[0], ast.Expr):
            return False
        if not isinstance(nodes[-1], ast.Num):
            return False
        nodes = nodes[1:-1]
        for i in range(len(nodes)):
            #if used + or - in digit :
            if i % 2 == 0:
                if not isinstance(nodes[i], ast.UnaryOp):
                    return False
            else:
                if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
                    return False
        return True
    else:
        return False

test:

>>> is_numeric("54")
True
>>> is_numeric("54.545")
True
>>> is_numeric("0x45")
True

is_float fonction

trouve si la variable donnée est flottante. flotteur de chaînes se composent d'un signe optionnel, un nombre quelconque de chiffres ...

import ast

def is_float(obj):
    if isinstance(obj, float):
        return True
    if isinstance(obj, int):
        return False
    elif isinstance(obj, str):
        nodes = list(ast.walk(ast.parse(obj)))[1:]
        if not isinstance(nodes[0], ast.Expr):
            return False
        if not isinstance(nodes[-1], ast.Num):
            return False
        if not isinstance(nodes[-1].n, float):
            return False
        nodes = nodes[1:-1]
        for i in range(len(nodes)):
            if i % 2 == 0:
                if not isinstance(nodes[i], ast.UnaryOp):
                    return False
            else:
                if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
                    return False
        return True
    else:
        return False

test:

>>> is_float("5.4")
True
>>> is_float("5")
False
>>> is_float(5)
False
>>> is_float("5")
False
>>> is_float("+5.4")
True

qu'est-ce que ast ?


2- Si vous êtes sûr que le contenu de la variable est chaîne de caractères :

utiliser str.appel isdigit() méthode

>>> a=454
>>> a.isdigit()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'isdigit'
>>> a="454"
>>> a.isdigit()
True

3-Entrée numérique:

détecter int valeur:

>>> isinstance("54", int)
False
>>> isinstance(54, int)
True
>>> 

détecter flotteur:

>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True
2
répondu 2018-10-06 07:23:24

j'ai aussi utilisé la fonction que vous avez mentionnée, mais bientôt je remarque que les chaînes comme" Nan"," Inf " et sa variation sont considérées comme nombre. Je vous propose donc une version améliorée de votre fonction, qui retournera false sur ce type d'entrée et ne manquera pas de variantes "1E3":

def is_float(text):
    try:
        float(text)
        # check for nan/infinity etc.
        if text.isalpha():
            return False
        return True
    except ValueError:
        return False
1
répondu mathfac 2016-10-15 21:11:09

si vous voulez savoir si la chaîne entière peut être représentée comme un nombre, vous voudrez utiliser un regexp (ou peut-être convertir le flotteur en une chaîne et le comparer à la chaîne source, mais je devine que ce n'est pas très rapide).

0
répondu m_eiman 2008-12-10 09:15:25

Voici ma façon simple de le faire. Disons que je suis en boucle sur certaines chaînes et je veux les ajouter à un tableau si elles se révèlent être des nombres.

try:
    myvar.append( float(string_to_check) )
except:
    continue

remplacer la myvar.apppend avec n'importe quelle opération que vous voulez faire avec la chaîne si elle s'avère être un nombre. L'idée est d'essayer d'utiliser un float() le fonctionnement et l'utilisation de l'a renvoyé l'erreur de déterminer si la chaîne est un nombre.

0
répondu 2009-07-16 17:45:12

vous pouvez généraliser la technique d'exception d'une manière utile en retournant des valeurs plus utiles que True et False. Par exemple cette fonction met des guillemets autour des chaînes mais laisse les nombres seuls. Ce qui est exactement ce dont j'avais besoin pour un filtre rapide et sale pour faire quelques définitions variables pour R.

import sys

def fix_quotes(s):
    try:
        float(s)
        return s
    except ValueError:
        return '"{0}"'.format(s)

for line in sys.stdin:
    input = line.split()
    print input[0], '<- c(', ','.join(fix_quotes(c) for c in input[1:]), ')'
0
répondu Thruston 2013-05-24 21:36:36

je travaillais sur un problème qui m'a conduit à ce fil, à savoir comment convertir une collection de données en chaînes et numéros de la manière la plus intuitive. J'ai réalisé après avoir lu le code original que ce dont j'avais besoin était différent de deux façons:

1-je voulais un résultat entier si la chaîne représentait un entier

2 - je voulais un nombre ou un résultat de chaîne de caractères pour coller dans une structure de données

donc j'ai adapté l'original code pour produire ce dérivé:

def string_or_number(s):
    try:
        z = int(s)
        return z
    except ValueError:
        try:
            z = float(s)
            return z
        except ValueError:
            return s
0
répondu user1508746 2014-11-09 14:06:38

essayez ceci.

 def is_number(var):
    try:
       if var == int(var):
            return True
    except Exception:
        return False
0
répondu TheRedstoneLemon 2015-05-30 17:12:56
import re
def is_number(num):
    pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')
    result = pattern.match(num)
    if result:
        return True
    else:
        return False


​>>>: is_number('1')
True

>>>: is_number('111')
True

>>>: is_number('11.1')
True

>>>: is_number('-11.1')
True

>>>: is_number('inf')
False

>>>: is_number('-inf')
False
0
répondu xin.chen 2018-08-02 11:06:14

utiliser la suite il traite tous les cas: -

import re
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3') 
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '.3')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3sd')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3')
-1
répondu donald 2017-02-24 11:11:51