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




python ziffern einer zahl (24)

isdigit() Sie nach Ganzzahlen (positive, unsigned) anstelle von isdigit() suchen, können Sie die Funktion isdigit() für String-Objekte verwenden.

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

Zeichenkettenmethoden - isdigit()

Es gibt auch etwas in Unicode-Strings, mit Unicode ist ich nicht so vertraut - ist dezimal / dezimal

Was ist die beste Möglichkeit zu überprüfen, ob eine Zeichenfolge in Python als Zahl dargestellt werden kann?

Die Funktion, die ich momentan gerade habe, ist:

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

Was nicht nur hässlich und langsam ist, wirkt klobig. Ich habe jedoch keine bessere Methode gefunden, weil float in der Hauptfunktion noch schlimmer ist.


Was nicht nur hässlich und langsam ist, wirkt klobig.

Es kann etwas gewöhnungsbedürftig sein, aber das ist die pythonische Art, es zu tun. Wie bereits erwähnt, sind die Alternativen schlechter. Aber es gibt einen weiteren Vorteil, die Dinge auf diese Weise zu tun: Polymorphismus.

Die zentrale Idee hinter der Eingabe von Enten ist, dass "wenn es wie eine Ente geht und spricht, dann ist es eine Ente." Was ist, wenn Sie sich entschließen, eine Unterklasse zu erstellen, damit Sie ändern können, wie Sie bestimmen, ob etwas in eine Gleitkomma umgewandelt werden kann? Oder was ist, wenn Sie sich entscheiden, ein anderes Objekt vollständig zu testen? Sie können diese Dinge tun, ohne den obigen Code ändern zu müssen.

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

Eine andere Sache, die Sie vielleicht in Betracht ziehen sollten: Python ist ziemlich schnell im Auswerfen und Abfangen von Ausnahmen im Vergleich zu vielen anderen Sprachen (30x schneller als. NET zum Beispiel). Ach ja, die Sprache selbst gibt sogar Ausnahmen aus, um nicht-außergewöhnliche, normale Programmbedingungen zu kommunizieren (jedes Mal, wenn Sie eine for-Schleife verwenden). Daher mache ich mir keine Gedanken über die Leistungsaspekte dieses Codes, bis Sie ein signifikantes Problem bemerken.


try: except: für Strings von Nicht-Zahlen try: except: ist eigentlich langsamer als reguläre Ausdrücke. Bei Strings mit gültigen Zahlen ist Regex langsamer. Die geeignete Methode hängt also von Ihrer Eingabe ab.

Wenn Sie feststellen, dass Sie sich in einer Leistungsbindung befinden, können Sie ein neues Modul von fastnumbers namens fastnumbers , das eine Funktion fastnumbers , die isfloat . Vollständige Offenlegung, ich bin der Autor. Ich habe seine Ergebnisse zu den Zeitpunkten unten eingefügt.

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 sehr langsam für eine ungültige Eingabe
  • Regex ist sehr effizient, wenn die Eingabe ungültig ist
  • fastnumbers gewinnt in beiden Fällen

If you want to know if the entire string can be represented as a number you'll want to use a regexp (or maybe convert the float back to a string and compare it to the source string, but I'm guessing that's not very fast).


Ich weiß, dass dies besonders alt ist, aber ich würde eine Antwort hinzufügen, die meiner Meinung nach die fehlenden Informationen aus der Antwort mit der höchsten Wahl abdeckt, die für jeden, der dies findet, sehr wertvoll sein könnte:

Für jede der folgenden Methoden verbinden Sie sie mit einer Zählung, wenn Sie eine Eingabe benötigen, um akzeptiert zu werden. (Angenommen, wir verwenden vokale Definitionen von Ganzzahlen anstelle von 0-255 usw.)

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

x.replace('-','').isdigit() funktioniert gut, um zu überprüfen, ob x negativ ist. (Check-in erste Position)

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

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

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


Try this.

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

Einfach C # imitieren

In C # gibt es zwei verschiedene Funktionen, die das Parsen von Skalarwerten behandeln:

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

float.parse ():

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

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

float.try_parse ():

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

Hinweis: Sie möchten den booleschen Wert 'Falsch' nicht zurückgeben, da dies immer noch ein Werttyp ist. Nichts ist besser, weil es einen Fehler anzeigt. Wenn Sie etwas anderes möchten, können Sie natürlich den Fehlerparameter auf das ändern, was Sie wollen.

Um Float auf 'parse ()' und 'try_parse ()' zu erweitern, müssen Sie die 'float' Klasse anpassen, um diese Methoden hinzuzufügen.

Wenn Sie vorbestehende Funktionen respektieren möchten, sollte der Code so 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 bevorzuge es, Monkey Punching zu nennen, weil es sich anfühlt, als würde ich die Sprache missbrauchen, wenn ich das mache, aber YMMV.

Verwendung:

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 die großen Weisen Pythonas sagten zum Heiligen Stuhl Sharpisus: "Alles, was du tun kannst, kann ich besser machen; ich kann alles besser als du."


Sagen wir, Sie haben Ziffern in der Zeichenfolge. str = "100949" und Sie möchten überprüfen, ob es nur Zahlen gibt

if str.isdigit():
returns TRUE or FALSE 

isdigit Dokumente

Andernfalls funktioniert Ihre Methode hervorragend, um das Auftreten einer Ziffer in einer Zeichenfolge zu finden.


Aktualisiert, nachdem Alfe darauf hingewiesen hat, dass Sie nicht separat nach Float suchen müssen.

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

    return True

Früher gesagt: In einigen seltenen Fällen müssen Sie auch nach komplexen Zahlen suchen (zB 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

RyanN schlägt vor

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

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


To check if the input value is a float , you can compare the type of the input to a float

def isFloat(s):
    realFloat = 0.1

    if type(s) == type(realFloat):
        return True
    else:
        return False

Kehrt zurück:

False     # s = 5
True      # s = 1.2345

Die ursprüngliche Post würde tatsächlich zurückkehren Truezu , s = 5da es eine Zahl (integer) und Sie können einen Guss intzu einem floatohne ValueError. Wenn Sie versuchen, zu überprüfen, ob es sich um eine tatsächliche floatZahl und nicht nur um eine Zahl handelt, müssen Sie diesen Fall berücksichtigen.


Um alles zusammenzufassen, indem man nach Nan, Unendlichkeit und komplexen Zahlen sucht (es scheint, dass sie mit j, nicht mit i, dh 1 + 2j spezifiziert sind), ergibt dies:

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

I also used the function you mentioned, but soon I notice that strings as "Nan", "Inf" and it's variation are considered as number. So I propose you improved version of your function, that will return false on those type of input and will not fail "1e3" variants:

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


Ich habe einen Geschwindigkeitstest gemacht. Nehmen wir an, wenn die Zeichenfolge wahrscheinlich eine Zahl ist, ist die try / except- Strategie die schnellste mögliche. Wenn die Zeichenfolge wahrscheinlich keine Zahl ist und Sie Interesse an Integer- Prüfung haben, lohnt es sich, einige Tests (isdigit plus heading) "-"). Wenn Sie Interesse haben, die Float-Nummer zu überprüfen, müssen Sie den try / exception-Code ohne escape verwenden.


Das Floaten und Abfangen von ValueError ist wahrscheinlich der schnellste Weg, da float () genau dafür gedacht ist. Alles andere, das das Parsen von Zeichenfolgen (Regex usw.) erfordert, wird wahrscheinlich langsamer sein, da es für diese Operation nicht optimiert ist. Meine $ 0,02.


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

Bitte beachten Sie, dass die Überprüfung auf eine erfolgreiche Besetzung die einzige Methode ist, die genau ist. Dies funktioniert beispielsweise mit check_exception aber die anderen beiden Testfunktionen geben False für einen gültigen 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 2017 MacBook Pro 13:

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 2017 MacBook Pro 13:

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

Es gibt eine Ausnahme, die Sie berücksichtigen sollten: die Zeichenfolge 'NaN'

Wenn Sie wollen, dass is_number FALSE für 'NaN' zurückgibt, wird dieser Code nicht funktionieren, da Python ihn in seine Darstellung einer Zahl umwandelt, die keine Zahl ist (sprechen Sie über Identitätsprobleme):

>>> float('NaN')
nan

Ansonsten sollte ich Ihnen tatsächlich für den Code danken, den ich jetzt ausgiebig verwende. :)

G.


Here's my simple way of doing it. Let's say that I'm looping through some strings and I want to add them to an array if they turn out to be numbers.

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

Replace the myvar.apppend with whatever operation you want to do with the string if it turns out to be a number. The idea is to try to use a float() operation and use the returned error to determine whether or not the string is a number.


You can generalize the exception technique in a useful way by returning more useful values than True and False. For example this function puts quotes round strings but leaves numbers alone. Which is just what I needed for a quick and dirty filter to make some variable definitions for 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:]), ')'

Für int verwenden Sie dies:

>>> "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 lstrip() einfach lstrip() :

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

Und jetzt bekommen wir einen universellen Weg:

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

You may use regex.

number = raw_input("Enter a number: ")
if re.match(r'^\d+$', number):
    print "It's integer"
    print int(number)
elif re.match(r'^\d+\.\d+$', number):
    print "It's float"
    print float(number)
else:
    print("Please enter a number")

Wie wäre es damit:

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

was nur dann wahr ist, wenn es ein oder kein '.' in der Ziffernfolge.

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

wird falsch zurückgeben

edit: habe gerade einen anderen Kommentar gesehen ... das Hinzufügen eines .replace(badstuff,'',maxnum_badstuff) für andere Fälle ist möglich. Wenn Sie Salz und nicht beliebige Gewürze (Ref: xkcd#974 ) passieren, wird dies gut tun: P


verwenden Sie folgendes behandelt alle Fälle: -

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






type-conversion