Wie erkennt man eine Gleitkommazahl mit einem regulären Ausdruck?

Was ist ein guter regulärer Ausdruck für die Verarbeitung einer Gleitkommazahl (dh wie Java’s Float)

Die Antwort muss mit folgenden Zielen übereinstimmen:

1) 1. 2) .2 3) 3.14 4) 5e6 5) 5e-6 6) 5E+6 7) 7.e8 8) 9.0E-10 9) .11e12 

Zusammenfassend sollte es so sein

  • vorherige Zeichen ignorieren
  • das erste Zeichen links vom Dezimalpunkt muss nicht Null sein
  • Erlaube 0 oder mehr Ziffern auf beiden Seiten des Dezimalpunkts
  • Erlaube eine Zahl ohne Dezimalpunkt
  • erlaube wissenschaftliche Notation
  • erlaubt Groß- oder Kleinbuchstaben ‘e’
  • erlaube positive oder negative Exponenten

Für diejenigen, die sich wundern, ja, das ist ein Hausaufgaben-Problem. Wir haben dies als eine Aufgabe in meiner Diplom-CS-class über Compiler erhalten. Ich habe meine Antwort für die class bereits abgegeben und werde sie als Antwort auf diese Frage veröffentlichen.

[Epilog] Meine Lösung wurde nicht vollständig gutgeschrieben, weil sie nicht mehr als 1 Stelle links vom Dezimaltrennzeichen behandelt hat. In der Zuweisung wurde die Behandlung von Java-Fließkommazahlen erwähnt, obwohl keines der Beispiele mehr als 1 Stelle links vom Dezimaltrennzeichen hatte. Ich werde die akzeptierte Antwort in ihrem eigenen Beitrag veröffentlichen.

Machen Sie sowohl den Dezimalpunkt als auch den E-then-Exponenten-Teil optional:

 [1-9][0-9]*\.?[0-9]*([Ee][+-]?[0-9]+)? 

Ich verstehe nicht, warum du kein führendes [+-]? willst [+-]? ein mögliches Zeichen auch zu erfassen, aber, was auch immer! -)

Edit : Es könnten tatsächlich keine Ziffern mehr vom Dezimalpunkt übrig bleiben (in diesem Fall stelle ich mir vor, dass es den Dezimalpunkt und 1+ Ziffern nach dem Komma geben muss !), So dass ein vertikaler Balken (Alternative) eindeutig benötigt wird:

 (([1-9][0-9]*\.?[0-9]*)|(\.[0-9]+))([Ee][+-]?[0-9]+)? 

[Dies ist die Antwort des Professors]

Definieren:

N = [1-9]
D = 0 | N
E = [eE] [+ -]? D +
L = 0 | (ND *)

Dann können Gleitkommazahlen abgeglichen werden mit:

((L. D * |. D +) E?) | (LE)

Es war auch akzeptabel, D + anstelle von L zu verwenden und [+ -]? Voranzustellen.

Ein häufiger Fehler war, D * zu schreiben. D *, aber das kann nur ‘.’

[Bearbeiten]
Jemand hat nach einem führenden Zeichen gefragt; Ich hätte ihn fragen sollen, warum es ausgeschlossen wurde, aber ich hatte nie die Chance. Da dies Teil der Vorlesung über Grammatiken war, vermute ich, dass es entweder das Problem leichter gemacht hat (nicht wahrscheinlich) oder dass es ein kleines Detail beim Parsen gibt, bei dem das Problem so aufgeteilt wird, dass der Fließkommawert unabhängig vom Vorzeichen ist der Fokus (möglich).

Wenn Sie einen Ausdruck analysieren, z

-5.04e-10 + 3.14159E10

Das Vorzeichen des Gleitkommawerts ist Teil der Operation, die auf den Wert angewendet werden soll, und nicht ein Attribut der Zahl selbst. Mit anderen Worten,

subtrahieren (5.04e-10)
hinzufügen (3.14159E10)

um das Ergebnis des Ausdrucks zu bilden. Während ich sicher bin, dass Mathematiker den Punkt streiten können, erinnern Sie sich, dass das von einer Vorlesung über das Parsing war.

Hier ist, was ich angestellt habe.

 (([1-9]+\.[0-9]*)|([1-9]*\.[0-9]+)|([1-9]+))([eE][-+]?[0-9]+)? 

Um die Diskussion zu erleichtern, beschrifte ich die Abschnitte

 ( ([1-9]+ \. [0-9]* ) | ( [1-9]* \. [0-9]+ ) | ([1-9]+)) ( [eE] [-+]? [0-9]+ )? -------------------------------------------------------- ----------------------  AB 

A: passt alles bis zum “e / E”
B: entspricht der wissenschaftlichen Notation

Zerbrechen A Wir bekommen drei Teile

  ( ([1-9]+ \. [0-9]* ) | ( [1-9]* \. [0-9]+ ) | ([1-9]+) ) ----------1---------- ---------2---------- ---3---- 

Teil 1: Erlaubt 1 oder mehr Ziffern von 1-9, Dezimalstellen, 0 oder mehr Nachkommastellen (Ziel 1)
Teil 2: Erlaubt 0 oder mehr Ziffern von 1-9, Dezimalstellen, 1 oder mehr Nachkommastellen (Ziel 2)
Teil 3: Erlaubt 1 oder mehr Ziffern von 1 bis 9 ohne Dezimalstelle (siehe Nr. 4 in der Zielliste)


B zerbrechen wir bekommen 4 grundlegende Teile

  ( [eE] [-+]? [0-9]+ )? ..--1- --2-- --3--- -4- .. 

Teil 1: erfordert entweder Groß- oder Kleinschreibung “e” für wissenschaftliche Notation (zB Ziele 8 & 9)
Teil 2: erlaubt ein optionales positives oder negatives Vorzeichen für den Exponenten (zB Ziele 4, 5, & 6)
Teil 3: Erlaubt 1 oder mehr Ziffern für den Exponenten (Ziel 8)
Teil 4: erlaubt die wissenschaftliche Notation als Gruppe (Ziel 3)

 '([-+])?\d*(\.)?\d+(([eE]([-+])?)?\d+)?' 

Das ist der reguläre Ausdruck, den ich gefunden habe, als ich versuchte, diese Art von Aufgabe in Matlab zu lösen. Tatsächlich erkennt es Zahlen wie (1.) nicht richtig, aber einige zusätzliche Änderungen können das Problem lösen … nun, vielleicht würde das Folgende das beheben:

 '([-+])?(\d+(\.)?\d*|\d*(\.)?\d+)(([eE]([-+])?)?\d+)?' 

@Kelly S. French: Das Zeichen fehlt, da es in einem Parser durch den unären Minus (Negation) -Ausdruck hinzugefügt wird, daher muss es nicht als Teil eines Floats erkannt werden.

@Kelly S. Französisch, dieser reguläre Ausdruck entspricht all Ihren Testfällen.

 ^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$ 

Quelle: perldoc perlretut