it-swarm.com.de

Wie überprüfe ich, ob eine Zeichenfolge eine Zahl ist (Float)?

Wie kann ich am besten überprüfen, ob eine Zeichenfolge in Python als Zahl dargestellt werden kann? 

Die Funktion, die ich momentan habe, ist:

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

Was nicht nur hässlich und langsam ist, scheint klobig zu sein. Ich habe jedoch keine bessere Methode gefunden, weil der Aufruf von float in der Hauptfunktion noch schlechter ist. 

1349
Daniel Goldberg

Was nicht nur hässlich und langsam ist

Ich würde beide bestreiten.

Ein Regex oder ein anderes String-Parsing wäre hässlicher und langsamer. 

Ich bin mir nicht sicher, ob etwas schneller sein könnte als das oben Genannte. Es ruft die Funktion auf und kehrt zurück. Try/Catch verursacht keinen großen Aufwand, da die häufigste Ausnahme ohne umfangreiche Suche nach Stack-Frames abgefangen wird.

Das Problem ist, dass jede numerische Konvertierungsfunktion zwei Arten von Ergebnissen hat

  • Eine Nummer, wenn die Nummer gültig ist
  • Ein Statuscode (z. B. über Fehlernummer) oder eine Ausnahme, um anzuzeigen, dass keine gültige Nummer analysiert werden kann.

C (als Beispiel) hackt einige Möglichkeiten. Python legt es klar und explizit dar.

Ich denke, Ihr Code dafür ist perfekt.

608
S.Lott

Wenn Sie nach Parsing-Werten (positiven, vorzeichenlosen) Ganzzahlen anstelle von Gleitkommazahlen suchen, können Sie die Funktion isdigit() für Stringobjekte verwenden.

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

String-Methoden - isdigit()

Es gibt auch etwas auf Unicode-Strings, mit dem ich nicht vertraut bin Unicode - Ist dezimal/dezimal

1421
Zoomulator

TL; DR Die beste Lösung ist s.replace('.','',1).isdigit()

Ich habe einige Benchmarks die verschiedenen Ansätze verglichen

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

Wenn der String keine Zahl ist, ist der Exceptor-Block ziemlich langsam. Noch wichtiger ist jedoch, dass die Try-Except-Methode der einzige Ansatz ist, der wissenschaftliche Notationen korrekt verarbeitet.

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" wird nicht unterstützt von:
- 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__)

Die wissenschaftliche Notation "1.000000e + 50" wird nicht unterstützt von:
- is_number_regex
- is_number_repl_isdigit
Wissenschaftliche Notation "1e50" wird nicht unterstützt von:
- is_number_regex
- is_number_repl_isdigit 

EDIT: Die Benchmark-Ergebnisse

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

wo die folgenden Funktionen getestet wurden

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

96
Sebastian

Es gibt eine Ausnahme, die Sie berücksichtigen möchten: Die Zeichenfolge "NaN"

Wenn Sie möchten, dass is_number für "NaN" FALSE zurückgibt, funktioniert dieser Code nicht, da Python es in eine Zahl konvertiert, die keine Zahl ist (sprechen Sie über Identitätsprobleme):

>>> float('NaN')
nan

Ansonsten sollte ich mich eigentlich für den Code bedanken, den ich jetzt ausgiebig verwende. :)

G.

66
gvrocha

wie wäre es damit:

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

die nur dann wahr zurückgeben wird, wenn es eine oder keine '.' in der Ziffernfolge.

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

wird falsch zurückkehren

edit: habe gerade einen weiteren Kommentar gesehen ... Hinzufügen einer .replace(badstuff,'',maxnum_badstuff) für andere Fälle kann gemacht werden. Wenn Sie salzige und nicht willkürliche Gewürze abgeben (ref: xkcd # 974 ), ist dies gut: P

53
haxwithaxe

Nachdem Alfe darauf hingewiesen hat, müssen Sie nicht mehr nach Float suchen, da komplexe Griffe beide sind:

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

    return True

Zuvor gesagt: In einigen seltenen Fällen müssen Sie möglicherweise auch nach komplexen Zahlen suchen (z. B. 1 + 2i), die nicht durch einen Float dargestellt werden können:

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
39

Was nicht nur hässlich und langsam ist, scheint klobig zu sein.

Es mag gewöhnungsbedürftig sein, aber dies ist die Pythonic-Methode. Wie bereits erwähnt, sind die Alternativen schlechter. Es gibt aber noch einen weiteren Vorteil, wenn man so vorgeht: Polymorphismus.

Die zentrale Idee hinter dem Entenschreiben lautet: "Wenn es wie eine Ente geht und spricht, dann ist es eine Ente." Was ist, wenn Sie entscheiden, dass Sie eine Zeichenfolge in einer Unterklasse definieren müssen, damit Sie ändern können, wie Sie feststellen, ob etwas in einen Float konvertiert werden kann? Oder wenn Sie sich entscheiden, ein anderes Objekt vollständig zu testen? Sie können diese Schritte ausführen, ohne den obigen Code ändern zu müssen.

Andere Sprachen lösen diese Probleme mithilfe von Schnittstellen. Ich werde die Analyse speichern, welche Lösung für einen anderen Thread besser ist. Der Punkt ist jedoch, dass Python sich entschieden auf der Enten-Seite der Gleichung befindet und Sie müssen sich wahrscheinlich an diese Syntax gewöhnen, wenn Sie vorhaben, viel in Python zu programmieren (was aber nicht bedeutet du musst es natürlich mögen).

Eine andere Sache, die Sie vielleicht in Betracht ziehen sollten: Python ist im Vergleich zu vielen anderen Sprachen (etwa 30x schneller als .Net) ziemlich schnell beim Werfen und Erfassen von Ausnahmen. Heck, die Sprache selbst löst sogar Ausnahmen aus, um nicht-außergewöhnliche, normale Programmbedingungen zu kommunizieren (jedes Mal, wenn Sie eine for-Schleife verwenden). Daher muss ich mich nicht zu sehr um die Leistungsaspekte dieses Codes kümmern, bis Sie ein erhebliches Problem feststellen.

37
Jason Baker

Für int verwenden Sie folgendes:

>>> "1221323".isdigit()
True

Aber für float brauchen wir ein paar Tricks ;-). Jede Float-Nummer hat einen Punkt ...

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

Auch für negative Zahlen fügen Sie einfach lstrip() hinzu:

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

Und jetzt bekommen wir einen universellen Weg:

>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False
19
Sdwdaw

Nur Mimik C #

In C # gibt es zwei verschiedene Funktionen, die die Analyse von Skalarwerten durchführen:

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

float.parse ():

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

Anmerkung: Wenn Sie sich fragen, warum ich die Ausnahme in einen TypeError geändert habe, dann hier ist die Dokumentation .

float.try_parse ():

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

Hinweis: Sie möchten nicht den booleschen Wert 'False' zurückgeben, da dies immer noch ein Werttyp ist. Keiner ist besser, da er auf einen Fehler hinweist. Wenn Sie etwas anderes möchten, können Sie den Parameter 'Fail' natürlich beliebig ändern .

Um Float zu erweitern, um 'parse ()' und 'try_parse ()' einzuschließen, müssen Sie die 'float'-Klasse monkeypatchen, um diese Methoden hinzuzufügen.

Wenn Sie bereits vorhandene Funktionen berücksichtigen möchten, sollte der Code wie folgt aussehen:

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

SideNote: Ich persönlich ziehe es vor, Monkey Punching zu nennen, weil es sich anfühlt, als würde ich die Sprache missbrauchen, wenn ich dies tue, außer YMMV.

Verwendungszweck:

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

Und der große Weise Pythonas sagte zu Sharpisus des Heiligen Stuhls: "Alles, was Sie tun können, kann ich besser; ich kann etwas besser als Sie."

15
Evan Plaice

Für Zeichenfolgen, die keine Zahlen sind, ist try: except: tatsächlich langsamer als reguläre Ausdrücke. Für Zeichenfolgen gültiger Zahlen ist der reguläre Ausdruck langsamer. Die geeignete Methode hängt also von Ihrer Eingabe ab. 

Wenn Sie feststellen, dass Sie sich in einem Performance-Bind befinden, können Sie ein neues Drittanbieter-Modul namens fastnumbers verwenden, das eine Funktion namens isfloat bereitstellt. Vollständige Offenlegung, ich bin der Autor. Ich habe die Ergebnisse in die Timings unten aufgenommen.


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

Wie du siehst

  • try: except: war schnell für die numerische Eingabe, aber für eine ungültige Eingabe sehr langsam
  • regex ist sehr effizient, wenn die Eingabe ungültig ist
  • fastnumbers gewinnt in beiden Fällen
15
SethMMorton

Ich weiß, dass dies besonders alt ist, aber ich würde eine Antwort hinzufügen, von der ich glaube, dass sie die Informationen abdeckt, die in der am besten bewerteten Antwort fehlen, die für jeden, der dies findet, sehr wertvoll sein könnten:

Verbinden Sie sie für jede der folgenden Methoden mit einer Zählung, wenn Eingaben akzeptiert werden müssen. (Angenommen, wir verwenden stimmliche Definitionen von Ganzzahlen anstelle von 0-255 usw.)

x.isdigit() funktioniert gut, um zu überprüfen, ob x eine ganze Zahl ist.

x.replace('-','').isdigit() funktioniert gut, um zu prüfen, ob x ein negatives Ergebnis ist.

x.replace('.','').isdigit() funktioniert gut, um zu prüfen, ob x eine Dezimalzahl ist.

x.replace(':','').isdigit() funktioniert gut, um zu prüfen, ob x ein Verhältnis ist.

x.replace('/','',1).isdigit() funktioniert gut, um zu prüfen, ob x ein Bruch ist.

12
Aruthawolf

Sie können Unicode-Zeichenfolgen verwenden. Sie haben eine Methode, um genau das zu tun, was Sie möchten:

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

Oder:

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

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

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

11
Blackzafiro

Das Floaten und Fangen von ValueError ist wahrscheinlich der schnellste Weg, da float () genau dafür gedacht ist. Alle anderen Elemente, für die eine Zeichenfolgenanalyse erforderlich ist (Regex usw.), sind wahrscheinlich langsamer, da sie für diesen Vorgang nicht geeignet sind. Meine $ 0,02.

10
codelogic

Ich wollte sehen, welche Methode am schnellsten ist. Insgesamt wurden die besten und konsistentesten Ergebnisse mit der Funktion check_replace erzielt. Die schnellsten Ergebnisse wurden von der check_exception-Funktion geliefert, jedoch nur, wenn keine Ausnahme ausgelöst wurde. Dies bedeutet, dass der Code der effizienteste ist, der Aufwand für das Auslösen einer Ausnahme jedoch recht groß ist.

Bitte beachten Sie, dass die Prüfung auf eine erfolgreiche Besetzung die einzige Methode ist, die genau ist. Dies funktioniert beispielsweise mit check_exception. Die anderen beiden Testfunktionen geben jedoch False für ein gültiges Float zurück:

huge_number = float('1e+100')

Hier ist der Benchmark-Code:

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

Hier sind die Ergebnisse mit Python 2.7.10 auf einem MacBook Pro 13 von 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

Hier sind die Ergebnisse mit Python 3.6.5 auf einem MacBook Pro 13 von 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

Hier sind die Ergebnisse mit PyPy 2.7.13 auf einem MacBook Pro 13 von 2017:

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
9
Ron Reiter

Diese Antwort enthält eine Schritt-für-Schritt-Anleitung mit Funktionen zum Auffinden der Zeichenfolge:

  • Positive ganze Zahl
  • Positiv/Negativ - Ganzzahl/Gleitkommazahl
  • Wie werden "NaN" - Zeichenfolgen (keine Zahl) verworfen, während nach Nummern gesucht wird?

Prüfen Sie, ob die Zeichenfolge positiv Integer ist

Sie können mit str.isdigit() prüfen, ob die angegebene Zeichenfolge positive integer ist. 

Beispielergebnisse:

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

Prüfen Sie, ob die Zeichenfolge positiv oder negativ ist (Ganzzahl/Gleitkommazahl)

str.isdigit() gibt False zurück, wenn die Zeichenfolge eine negative-Nummer oder eine Float-Nummer ist. Zum Beispiel:

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

Wenn Sie auch nach negativen Ganzzahlen und float suchen möchten, können Sie eine benutzerdefinierte Funktion schreiben, um dies zu prüfen:

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

Probelauf:

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

Verwerfen Sie die Zeichenfolgen "NaN" (keine Zahl), während Sie die Anzahl überprüfen

Die obigen Funktionen geben True für die Zeichenfolge "NAN" (Keine Zahl) zurück, da es sich bei Python um einen gültigen Float handelt, der darstellt, dass es keine Zahl ist. Zum Beispiel:

>>> is_number('NaN')
True

Um zu prüfen, ob die Nummer "NaN" ist, können Sie math.isnan() als:

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

>>> math.isnan(nan_num)
True

Wenn Sie keine zusätzliche Bibliothek importieren möchten, um dies zu überprüfen, können Sie sie einfach überprüfen, indem Sie sie mit == mit sich selbst vergleichen. Python gibt False zurück, wenn nan float mit sich selbst verglichen wird. Zum Beispiel:

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

Daher kann über function is_number aktualisiert werden, um False für "NaN" als zurückzugeben:

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

Probelauf:

>>> 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: Jede Operation für jede Prüfung, abhängig von der Art der Nummer, ist mit zusätzlichem Aufwand verbunden. Wählen Sie die Version der is_number-Funktion, die Ihrer Anforderung entspricht.

8

Nehmen wir an, Sie haben Ziffern in der Zeichenfolge . Str = "100949" Und Sie möchten prüfen, ob nur Zahlen vorhanden sind

if str.isdigit():
returns TRUE or FALSE 

isdigit docs

ansonsten funktioniert Ihre Methode hervorragend, um das Vorkommen einer Ziffer in einer Zeichenfolge zu finden. 

7
Clayton

Um es zusammenzufassen: Wenn Sie nach Nan, Unendlich und komplexen Zahlen suchen (es scheint, als würden sie mit j angegeben, nicht mit i, d. H. 1 + 2j), ergibt sich

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
a1an

Ihr Code sieht gut aus für mich.

Vielleicht denken Sie, dass der Code wegen Ausnahmen "klobig" ist? Beachten Sie, dass Python-Programmierer aufgrund ihrer geringen Leistungseinbußen meist großzügig Ausnahmen verwenden, wenn sie die Lesbarkeit von Code verbessern.

5
Dubhead

Ich musste feststellen, ob eine Zeichenfolge in Basistypen (float, int, str, bool) umgewandelt wird. Nachdem ich im Internet nichts gefunden habe, habe ich folgendes erstellt:

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)

Beispiel

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       

Sie können den Typ erfassen und verwenden 

s = "6.0"
type_ = str_to_type(s) # float
f = type_(s) 
4
astrodsg

Ich habe einen Geschwindigkeitstest gemacht. Nehmen wir an, wenn die Zeichenfolge wahrscheinlich eine Zahl ist, ist die Strategie try/except die schnellste. Wenn die Zeichenfolge ist ist nicht wahrscheinlich um eine Zahl zu sein nd Sie interessieren sich für Integer Überprüfen Sie, ob es sich lohnt, einen Test durchzuführen (isdigit plus Überschrift '-') . Wenn Sie die Float-Nummer überprüfen möchten, müssen Sie den try/except Code ohne Escape verwenden.

4
FxIII

Die Eingabe kann wie folgt sein:

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


1-Allgemeine Eingabe:

Die Eingabe dieser Funktion kann alles sein!

Findet, ob die angegebene Variable numerisch ist. Numerische Zeichenfolgen bestehen aus einem optionalen Vorzeichen, einer beliebigen Anzahl von Ziffern, einem optionalen Dezimalteil und einem optionalen Exponentialteil. Somit ist + 0123.45e6 ein gültiger numerischer Wert. Hexadezimal-Schreibweise (z. B. 0xf4c3b00c) und binäre Schreibweise (z. B. 0b10100111001) ist nicht zulässig.

is_numeric Funktion

import ast
import numbers              
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

prüfung:

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

is_float -Funktion

Findet, ob die angegebene Variable float ist. Float-Strings bestehen aus optionalen Zeichen, einer beliebigen Anzahl von Ziffern, ...

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

prüfung:

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

was ist ast ?


2- Wenn Sie sicher sind, dass der variable Inhalt String ist:

verwenden Sie str.isdigit () Methode

>>> 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-numerische Eingabe:

int-Wert ermitteln:

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

Float erkennen:

>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True
3
user10461621

RyanN schlägt vor

Wenn Sie für NaN und Inf False zurückgeben möchten, ändern Sie die Zeile in x = float (s); return (x == x) und (x - 1! = x). Dies sollte für alle Floats mit Ausnahme von Inf und NaN True zurückgeben

Dies funktioniert jedoch nicht ganz, denn x-1 == x gibt für ausreichend große Floats true zurück. Zum Beispiel 2.0**54 - 1 == 2.0**54

3
philh

Ich habe auch die von Ihnen erwähnte Funktion verwendet, aber bald bemerke ich, dass Strings als "Nan", "Inf" und deren Variation als Zahl betrachtet werden. Ich schlage also vor, Sie haben eine verbesserte Version Ihrer Funktion, die bei dieser Art der Eingabe false zurückgibt und "1e3" -Varianten nicht versagt:

def is_float(text):
    try:
        float(text)
        # check for nan/infinity etc.
        if text.isalpha():
            return False
        return True
    except ValueError:
        return False
1
mathfac

Sie können die Ausnahmetechnik sinnvoll verallgemeinern, indem Sie nützlichere Werte als "Wahr" und "Falsch" zurückgeben. Diese Funktion setzt beispielsweise Anführungszeichen in runde Zeichenketten, lässt aber Zahlen allein. Genau das brauchte ich für einen schnellen und schmutzigen Filter, um einige Variablendefinitionen für R zu erstellen. 

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
Thruston

Versuche dies.

 def is_number(var):
    try:
       if var == int(var):
            return True
    except Exception:
        return False
0

Benutzerhilfefunktion:

def if_ok(fn, string):
  try:
    return fn(string)
  except Exception as e:
    return None

dann

if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str)
is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])
0
Samantha Atkins

Wenn Sie wissen möchten, ob die Zeichenfolge complete als Zahl dargestellt werden kann, möchten Sie einen Regex verwenden (oder den Float zurück in eine Zeichenfolge konvertieren und mit der Quellzeichenfolge vergleichen das ist nicht sehr schnell).

0
m_eiman

Ich denke, deine Lösung ist in Ordnung.

Trotzdem gibt es eine Menge Hass gegen diese Antworten, die ich für ungerechtfertigt halte. Regexps können einigermaßen sauber, korrekt und schnell sein. Es hängt wirklich davon ab, was Sie versuchen. Die ursprüngliche Frage war, wie Sie "überprüfen können, ob eine Zeichenfolge als Zahl (Float) dargestellt werden kann" (gemäß Ihrem Titel). Vermutlich möchten Sie den numerischen/float-Wert verwenden, sobald Sie überprüft haben, ob er gültig ist. In diesem Fall ist Ihr try/except sehr sinnvoll. Aber wenn Sie aus irgendeinem Grund nur prüfen möchten, ob ein String eine Zahl ist, funktioniert auch ein regulärer Ausdruck, aber es ist schwierig, ihn zu korrigieren. Ich denke, die meisten der bisherigen Regex-Antworten analysieren beispielsweise Strings ohne einen ganzzahligen Teil (wie ".7"), der für Python ein Float ist, nicht richtig. Und es ist etwas schwierig, in einem einzelnen Regex nach dem Bruchteil zu suchen, der nicht benötigt wird. Ich habe zwei reguläre Ausdrücke eingefügt, um dies zu zeigen.

Es wirft die interessante Frage auf, was eine "Zahl" ist. Enthalten Sie "inf", das als Float in Python gültig ist? Oder schließen Sie Zahlen ein, die "Zahlen" sind, aber möglicherweise nicht in Python dargestellt werden können (z. B. Zahlen, die größer sind als das Float-Maximum).

Es gibt auch Unklarheiten, wie Sie Zahlen analysieren. Was ist zum Beispiel mit "--20"? Ist das eine "Nummer"? Ist dies eine legale Möglichkeit, "20" darzustellen? In Python können Sie "var = --20" eingeben und auf 20 setzen (obwohl dies in Wirklichkeit darauf zurückzuführen ist, dass es als Ausdruck behandelt wird), aber float ("- 20") funktioniert nicht.

Wie auch immer, ohne weitere Informationen, hier ist ein regulärer Ausdruck, von dem ich glaube, dass er alle Ints und Floats abdeckt wie Python sie parst .

# Doesn't properly handle floats missing the integer part, such as ".7"
SIMPLE_FLOAT_REGEXP = re.compile(r'^[-+]?[0-9]+\.?[0-9]+([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56"      # sign (-)
                            #     integer (12)
                            #           mantissa (34)
                            #                    exponent (E+56)

# Should handle all floats
FLOAT_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56"      # sign (-)
                            #     integer (12)
                            #           OR
                            #             int/mantissa (12.34)
                            #                            exponent (E+56)

def is_float(str):
  return True if FLOAT_REGEXP.match(str) else False

Einige Beispieltestwerte:

True  <- +42
True  <- +42.42
False <- +42.42.22
True  <- +42.42e22
True  <- +42.42E-22
False <- +42.42e-22.8
True  <- .42
False <- 42nope
0

Dieser Code behandelt die Exponenten, Gleitkommazahlen und Ganzzahlen, ohne Regex zu verwenden.

return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False
0
ravi tanwar

Hier ist meine einfache Art, es zu tun. Nehmen wir an, ich durchsehe einige Zeichenketten und möchte sie zu einem Array hinzufügen, wenn sie Zahlen sind.

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

Ersetzen Sie myvar.apppend durch eine beliebige Operation, die Sie mit der Zeichenfolge ausführen möchten, wenn sich herausstellt, dass es sich um eine Zahl handelt. Die Idee ist, zu versuchen, eine float () - Operation zu verwenden, und den zurückgegebenen Fehler zu verwenden, um festzustellen, ob die Zeichenfolge eine Zahl ist oder nicht.

0
Anil

Ich arbeitete an einem Problem, das mich zu diesem Thread führte, nämlich wie eine Sammlung von Daten auf intuitivste Weise in Strings und Zahlen umgewandelt werden kann. Nachdem ich den Originalcode gelesen hatte, wurde mir klar, dass das, was ich brauchte, in zweierlei Hinsicht anders war:

1 - Ich wollte ein ganzzahliges Ergebnis, wenn die Zeichenfolge eine ganze Zahl darstellt

2 - Ich wollte, dass eine Zahl oder ein String-Ergebnis in eine Datenstruktur eingefügt wird

also habe ich den Originalcode angepasst, um diese Ableitung zu erzeugen:

def string_or_number(s):
    try:
        z = int(s)
        return z
    except ValueError:
        try:
            z = float(s)
            return z
        except ValueError:
            return s
0
user1508746
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
xin.chen