Seite 3 von 4

Verfasst: 20.07.2008 21:56
von Kaeru Gaman
Josef Sniatecki hat geschrieben:Doch irgendwie finde ich das ein bisschen unprofessionell. Oder bin ich der einzige der das so sieht?
ich finde, einen eigenen Stack zu schreiben wenn der des Systems nicht ausreicht,
ist eher als besonders professionell zu betrachten.

Verfasst: 21.07.2008 18:57
von Josef Sniatecki
OK, dann werde ich mal mein Template umprogrammieren. Doch erst einmal
arbeite ich an einem anderen Projekt.

Verfasst: 21.07.2008 19:40
von Little John
Josef Sniatecki hat geschrieben:OK. Das mit der Division durch 0 ist leicht zu beheben. Doch das mit den
vielen Klammern nicht. "CalcStr" muss einfach eine neue Ebene bei jeder
Klammer öffnen, sonst wird die Priorität nicht beachtet.
Das ist klar, das macht mein Code ja auch.
Trotzdem kann mein Code solche tief verschachtelten Formeln berechnen, und auch welche die noch tiefer verschachtelt sind, z.B.

Code: Alles auswählen

XIncludeFile "calc.pbi"

Debug Calc("1+(2+(3+(4+(5+(6+(7+(8+(9-(10+(11+(12+(13+(14+(15+(16-(17+(18+(19+(20)))))))))))))))))))")
;-- Berechnung direkt durch PB zur Kontrolle:
Debug       1+(2+(3+(4+(5+(6+(7+(8+(9-(10+(11+(12+(13+(14+(15+(16-(17+(18+(19+(20)))))))))))))))))))
Kaeru Gaman hat geschrieben:ich finde, einen eigenen Stack zu schreiben wenn der des Systems nicht ausreicht,
ist eher als besonders professionell zu betrachten.
Da stimme ich Dir im Prinzip zu, nur ist das Problem hier ein anderes.
Wie man sieht reicht der Stack des Systems für sauber programmierte Rekursion hier durchaus aus.

Gruß, Little John

Verfasst: 22.07.2008 19:31
von Josef Sniatecki
Nun bin ich am Grübeln :?

Verfasst: 22.07.2008 20:12
von Little John
AND51 hat geschrieben:Wollte auch schon immer mal sowas coden.

Ich finde die Idee mit der Rekusrion sehr elegant. Es ist naheliegend, für jkeden neuen Teilterm die Prozedur erneut aufzurufen.

Was haltet ihr denn von der Idee, alle Teilterme z. B. per RegExp zu separieren. Diese lägen dann in einem Array vor, welches man durchlaufen könnte.
Das hört sich eher nach dem umgekehrten Ansatz -- also einer Bottom-Up-Methode an. Hier würde man selbst die Datenstrucktur Stack implementieren und "verwalten". Da PureBasic i. Ggs. zu vielen anderen prozeduralen Sprachen den Vorteil hat, LinkedLists elegant und direkt zu unterstützen, würde ich diese für den selbstgemachten Stack einem Array vorziehen; denn bei LinkedLists muss man sich keine Gedanken darüber machen, wieviel Platz man reservieren soll.

Mit RegEx kenne ich mich nicht gut aus. Aber Du schon, denke ich ... => mach mal! :)

Gruß, Little John

Verfasst: 22.07.2008 20:16
von Josef Sniatecki
Ich kenne mich zwar mit RegEx aus, jedoch habe ich noch PB 4.00
(Habe (noch) keine Updateberechtigung). :(

Verfasst: 22.07.2008 20:22
von Little John
Ähm, ich hoffe das wird jetzt nicht zu sehr off topic aber ... ich dachte jeder hat eine Updateberechtigung.

Gruß, Little John

Verfasst: 22.07.2008 20:23
von AND51
Little John hat geschrieben:würde ich diese für den selbstgemachten Stack einem Array vorziehen; denn bei LinkedLists muss man sich keine Gedanken darüber machen, wieviel Platz man reservieren soll.
Der Befehl ExtractRegularExpression() speichert alle Teilstrings in Arrays ab, nicht in LinkedLists.

Meine Idee war, aus dem String "5+7*10" folgendes zu machen:

Code: Alles auswählen

Dim teil.s(4)

teil(0)="5"
teil(1)="+"
teil(2)="7"
teil(3)="*"
teil(4)="10"
Jetzt könnte man das Array bequem durchlaufen und von links nach rechts berechnen.

Die einzige Schwierigkeit, die ich sehe, ist die Beachtung der Priorität der verschiedenen mathematischen Operatoren, d. h. Punkt- vor Strichrechnung. Und wenn man später noch Funktionen einfügen will, z. B. "5+7*sin(90)" oder so, da müsste man nach den passenden Ausdrücken suchen.

Werde mich bei Zeiten mal an einen kleinen Anfang wagen.

Verfasst: 22.07.2008 20:36
von Little John
AND51 hat geschrieben:
Little John hat geschrieben:würde ich diese für den selbstgemachten Stack einem Array vorziehen; denn bei LinkedLists muss man sich keine Gedanken darüber machen, wieviel Platz man reservieren soll.
Der Befehl ExtractRegularExpression() speichert alle Teilstrings in Arrays ab, nicht in LinkedLists.
Ach sooo ... Da siehst Du mal, wie wenig ich mich damit auskenne. :-)
AND51 hat geschrieben:Meine Idee war, aus dem String "5+7*10" folgendes zu machen:

Code: Alles auswählen

Dim teil.s(4)

teil(0)="5"
teil(1)="+"
teil(2)="7"
teil(3)="*"
teil(4)="10"
Genau. Aufteilen des Quellstrings in die einzelnen sog. Token (= Folge von Zeichen, die bedeutungsmäßig zusammen gehören). Das ist der erste Schritt.
AND51 hat geschrieben:Jetzt könnte man das Array bequem durchlaufen und von links nach rechts berechnen.

Die einzige Schwierigkeit, die ich sehe, ist die Beachtung der Priorität der verschiedenen mathematischen Operatoren, d. h. Punkt- vor Strichrechnung. Und wenn man später noch Funktionen einfügen will, z. B. "5+7*sin(90)" oder so, da müsste man nach den passenden Ausdrücken suchen.
Ja, das mit den Prioritäten, inklusive verschachtelten Klammern, ist eben die "Herausforderung". Das macht man halt normalerweise beim Top-Down-Ansatz rekursiv, und beim Bottom-Up-Ansatz mit einem eigenen Stack.

Gruß, Little John

Verfasst: 23.07.2008 12:17
von AND51
> Top-Down-Ansatz
Das ist also die Methode, wenn man innerste Klammern zuerst berechnet und dieses Teilergebnis rekursiv zurü+ckgibt, bis man "unten", also auf äußerster Ebene angekommen ist?
Wenn ja, fände ich das auf Anhieb einfach, es so zu probieren.

> Bottom-Up-Ansatz
Und das ist meine 2. Idee, alles in ein Array zu separieren?
Hier habe ich mal mit Regulären Ausdrücken versucht, einen Teststring zu separieren.
Bis jetzt separiert er nur Zahlen und Nicht-Zahlen. Nicht-Zahlen sind also Mathematische Operatoren.

So meinst du das doch, oder?

Code: Alles auswählen

term.s="(54+77.8)-6*3+90"

Procedure.d EvaluateMathExpression(term.s)
	Protected Dim subterm.s(0)
	Protected exp=CreateRegularExpression(#PB_Any, "([\d.]+|\D{1})")
	Protected n, anzahl=ExtractRegularExpression(exp, term, subterm())

	For n=0 To anzahl-1
		Debug subterm(n)
	Next

	FreeRegularExpression(exp)
EndProcedure

EvaluateMatheExpression(term)
Wir können ja mal versuchen, so eine Prozedur zu entwickeln. Ganz unverbindlich und wenn es uns zu schwer wird, lassen wir's.

1. ExtractRegularExpression() speichert alle Teilstrings in einem Array und gibt die Anzahl gefundener Teilstrings zurück
2. Ab der For-Schleife dürftest du jetzt werkeln, denn ab hier ist "meine" Arbeit erledigt.
3. Noch dürfen Zahlen beliebig viele Kommas enthalten. er akzeptiert also auch Zahlen wie "77..8.4".

Was sagst du bisher dazu?