| Autor |
Beitrag |
Benutzername 
      
Beiträge: 210
Win XP Pro
Delphi 7 PE, D2005 Prof. SSL
|
Verfasst: So 07.08.05 16:07
Ja, so ganz begeistert war ich von den Regular Expressions auch nicht, aber wenns funktioniert...
Du sagst, man sollte das mit nem Baum lösen: Gibts da schon ne fertige Klasse in Delphi, mit der man daslösen könnte?
Und noch ne andere Frage: Angenommen ich hab jetzt einfach nen Term wie 3+6*5*7. Wie mach ich dem Parser klar, dass er doch bitte Punkt-vorStrich beachten soll? Such ich da "einfach" nach dem ersten vorkommenden * oder / -Zeichen und schau dann, welche Zahlen drumrum stehen?
Vermute ich richtig, dass ich zuerst alle Klammern von innen nach außen ausrechnen muss?
Weil dann mach ich mich zuerst mal an ne Funktion, die mir den Term in der innersten Klammer raussucht 
|
|
LigH
      
Beiträge: 239
Win98SE, Win2000SP4
D7
|
Verfasst: So 07.08.05 21:44
Es wird sicher darauf ankommen, welche Operanden du überhaupt zuläßt (unäre, binäre, Funktionen, Klammern, evtl. noch logische?) - "Punkt vor Strich" ist ja nur eine Ebene, ich kenne Parser mit mehr als einem halben Dutzend Operanden-Hierarchie-Ebenen.
Und da - wenn du einen Zweig des Baumes als Operand ansiehst, und ein Blatt als Operator - jeder Operanden-Zweig sowohl unterschiedlich viele Verzweigungen haben kann, als auch unterschiedliche Inhalte (entweder ein Operanden-Blatt, oder einen kompletten neuen Operatoren-Zweig), wäre mit Sicherheit eine eigene Klassenheirarchie sinnvoll, so etwas dürfte man kaum fertig vorfinden.
|
|
Benutzername 
      
Beiträge: 210
Win XP Pro
Delphi 7 PE, D2005 Prof. SSL
|
Verfasst: So 07.08.05 23:28
Hm, klingt recht kompliziert  *g*
Ich werds mir bei Gelegenheit nochmal durch den Kopf gehen lassen^^
Aber ich hab nun einfach mal so drauflos geschrieben, und hab meinen Parser nun soweit, dass er * und / -Rechnungen richtig ausrechnet
Jetz fehlen "nurnoch" + und - Rechnungen und vielleicht Potenzen.
Und das unäre Minus muss ich noch einbauen, dass passt die Sache *g*
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mo 08.08.05 04:28
Benutzername hat folgendes geschrieben: | | Vermute ich richtig, dass ich zuerst alle Klammern von innen nach außen ausrechnen muss? |
Es gibt Parsers, die arbeiten von aussen nach innen; es gibt welche, die arbeiten von innen nach aussen. Du kannst einen Parser (iirc) sogar mit einer Finite State Maschine programmieren (à la Windows-Calculator). Es gibt bestimmt mind. 5 komplett verschiedene Ansätze, wie man das programmieren kann.
Ich bevorzuge meine rekursive Variante (keine Finite State Maschine), die den String mehr oder weniger einmal von links nach rechts passiert. Die Rekursion ist dabei so gemacht, dass man direkt die richtige Reihenfolge der Operationen für die Umwandlung zu Maschinencode erhält.
Beispiel:
1+(2+3)*(4+5)
Der Parser bringt das ganze in folgende Reihenfolge:
1 2 3 + 4 5 + * +
Zum Auswerten geht man diese Liste von links nach rechts durch. Man muss dabei lediglich zwei Regeln beachten:
- Eine Zahl wird auf den Stack gepusht.
- Eine binäre Operationen "poppt" zwei Zahlen aus dem Stack, führt die Operation durch und pusht anschliessend wieder das Ergebnis.
Beispiel:
Zeitschritt Token Stack Rechnung
0 []
1 1 [1]
2 2 [1,2]
3 3 [1,2,3]
4 + [1] 2+3
5 [1,5]
6 4 [1,5,4]
7 5 [1,5,4,5]
8 + [1,5] 4+5
9 [1,5,9]
10 * [1] 5*9
11 [1,45]
12 + [] 1+45
13 [46]
(46 ist das Ergebnis)
Mein Parser beschäftigt sich also vereinfacht gesprochen mit der Aufgabenstellung
1+(2+3)*(4+5)
in
1 2 3 + 4 5 + * +
umzuwandeln.
|
|
Benutzername 
      
Beiträge: 210
Win XP Pro
Delphi 7 PE, D2005 Prof. SSL
|
Verfasst: Mo 08.08.05 16:15
Ah, Danke für die Erklärung, Hintergrundwissen ist immer gut
Aber ich hab das jetz ohne die Postfix-Notation gemacht (so heißt die doch (bzw. UPN) ? *gg*) und auch ohne Stack.
Alles was jetzt noch fehlt, ist die Rechnung mit Potenzen und das mit den negativen Zahlen.
Wobei Potenzen schnell einzubauen sind *g*
Ich parse jetzt einfach die Klammern von innen nach außen, bis ich beim "Grundterm" angekommen bin, und löse das dann so auf, klappt auch wunderbar. Nicht-Ganzzahlen kann er auch schon, war auch kein Problem
Ich meld mich wieder, wenns Neuigkeiten und/oder Fragen gibt :stupid:
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mo 08.08.05 17:12
Benutzername hat folgendes geschrieben: | | Aber ich hab das jetz ohne die Postfix-Notation gemacht (so heißt die doch (bzw. UPN) ? *gg*) und auch ohne Stack. |
Yep, Infix heisst die "normale" Schreibweise und Postfix die Notation mit den nachgestellten Operatoren (aka. RPN (UPN ist wohl Deutsch)).
Benutzername hat folgendes geschrieben: | | Ich meld mich wieder, wenns Neuigkeiten und/oder Fragen gibt :stupid: |
Anschliessend einige Ausdrücke, die ich testen würde:
1-(-1) = 2 (Doppelnegation)
-2^2 = -4 (Hoch vor Punkt vor Strich)
(-2)^2 = 4 (ausser bei Klammerung...)
2^3^4 = mathematisch gesehen 2.4179e+024, bei Taschenrechnern (z.B. der Firma TI) z.T. aber auch 4096
1+(-(1+2)) = -2 (Negation einer Klammer)
je nachdem sollten auch folgende Ausdrücke akzeptiert werden:
1---2 = -3 (verschachtelte Minusoperationen)
1*-2 = -2 (Negation ohne explizite Klammerung)
1e+3^2 = 1000000 ("1e+3" ist eine korrekte Float-Zahl)
9^5e-1 = 3 (ditto)
2(3) = 6 (Standardoperator = "*")
|
|
LigH
      
Beiträge: 239
Win98SE, Win2000SP4
D7
|
Verfasst: Mo 08.08.05 19:06
UPN (Umgekehrte Polnische Notation) ist das, das mit dem Stack arbeitet - "Postfix-Notation". "Infix" ist die aus der Schule gewohnte Schreibweise.
|
|
Benutzername 
      
Beiträge: 210
Win XP Pro
Delphi 7 PE, D2005 Prof. SSL
|
Verfasst: Mi 10.08.05 17:13
So, er ist nun fertig
@delphifan: Danke für die Ausdrücke die ich testen sollte, klappt wunderbar
Aber zu deinem zweiten Beispiel hätt ich noch ne Frage:
Du sagtest ja, dass -2^2 = -4 ist, wegen Hoch vor Punkt vor Strich, hab ich auch verstanden
Aber angenommen, ich hätte --2^2. Wäre das dann das gleiche wie -(-2^2) oder wäre das dann -(-2)^2 ?
Da blick ich nämlich noch net ganz durch *g*
//edit: Noch was *g*
Gibts irgendwelche Vergleichswerte von der Geschwindigkeit her, wo ich in etwa liege?
Das wäre find ich ganz interessant zu wissen. 
|
|
AXMD
      
Beiträge: 4006
Erhaltene Danke: 7
Windows 10 64 bit
C# (Visual Studio 2019 Express)
|
Verfasst: Mi 10.08.05 17:22
--2^2 = 2^2 = 4
nur wenn du -(-2)^2 hast, erhältst du -4.
AXMD
|
|
Benutzername 
      
Beiträge: 210
Win XP Pro
Delphi 7 PE, D2005 Prof. SSL
|
Verfasst: Mi 10.08.05 17:27
Okay, Danke
Alles, was ich wissen wollte *g*
Dann bügel ich den Fehler noch schnell aus (war mir nämlich nicht sicher) und dann kann ich den Parser (mit Beispielprojekt) ja mal posten, wenns jemanden interessiert *g*
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 10.08.05 18:11
Ich teste ihn gern aus für dich. Ich hab sicher schon 5 verschiedene Parser auf Herz und Nieren geprüft
Geschwindigkeitsmässig müsste man unterscheiden zwischen Parsen und Auswerten. Mein Parser und auch andere Parser parsen zuerst den Ausdruck und erzeugen daraus einen Bytecode, Maschinencode oder sonst eine schnell auswertbare Struktur (wie z.B. Bäume). So kann ein Ausdruck schnell mehrmals ausgewertet werden (z.B. zum Graphen zeichnen).
Die eigentliche Auswertung geht dann relativ schnell; das Parsen geht etwas länger.
|
|
Benutzername 
      
Beiträge: 210
Win XP Pro
Delphi 7 PE, D2005 Prof. SSL
|
Verfasst: Mi 10.08.05 18:20
Okay, dann wende ich mich mal per PN an delfiphan und wenn dann alles funktioniert, stell ich ihn hier rein 
Zuletzt bearbeitet von Benutzername am Mi 10.08.05 18:59, insgesamt 2-mal bearbeitet
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 10.08.05 18:22
Die PN schreibst du am besten an del fi phan
Bin ja schon gespannt...
|
|