| Autor |
Beitrag |
Xardas008
      
Beiträge: 149
Win 7 Professional x64, Ubuntu 10.04, Windows Server 2008 R2
C#, Visual Studio 2008 Pro, Visual Studio 2010 Ultimate, Eclipse (Java)
|
Verfasst: Do 29.03.07 12:04
Hi ihr,
das Problem klingt komplizierter als es ist. Ich bin gerade einen Taschenrechner am programmieren, der auch Punkt vor Strichrechnung beherrscht.
Funktioniert soweit auch schon ganz gut.
Nur an einer Stelle hapert es, der Array, wo ich die eingegebenen Zahlen aus dem Editfeld drin speichere, müssen umsortiert werden, da ich intern Klammern in das Operatorenarray einfüge, wenn der Operator ein * oder ein / ist, damit der dies zuerst rechnet.
Das Problem durch die Klammern ist dann, dass die Reihenfolge der Zahlen nicht mehr stimmt, sie müssen neu sortiert werden.
Für die Rechnung 1 + 2x3 - 1/2 +6 muss der Taschenrechner intern folgendes machen, er rechnet erst 2x3, dazu addiert er die 1. Um jetzt 1/2 rechnen zu können, müssen beide Elemente im Array um 1 nach hinten geschoben werden (alle dahinter natürlich auch), um dann die +6 zu rechnen, muss die 6 ein weiteres mal nach hinten geschoben werden, usw.
Irgendwie bekomme ich die Prozedur dafür nicht so recht hin, wollte das ganze Rekursiv lösen, wobei beide Arrays dieser Prozedur übergeben werden müssen.
Hoffe dass ich mit Eurer Hilfe das hinbekomme, dann kann ich auch noch nachträglich Klammernsetzung einfügen (weil die sind nach mathematischen Gesetzen ja noch vor dem Punkt (* oder /) zu lösen.
Mit freundlichen Grüßen
Xardas008
Edit: Liefere euch hier mal eben die prozeduren GetNumber und SetOperator, wo die beiden Arrays gefüllt werden.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62:
| function TFrm_Taschenrechner.GetNumbers(vNumber:STRING):Number; var i, k:INTEGER; dummy:REAL; dummy3 :ARRAY[1..40] of REAL; dummy2 :StringArray; dummy4 :char; begin j := 0; for i := 1 to Length(vNumber) do begin
if not(vNumber[i] = '|') then begin
if vNumber[i] = '|' then begin inc(j); end else begin
inc(j); Number2[j] := StrToFloat(vNumber[i]); end; end; end; result := Number2; end;
function TFrm_Taschenrechner.SetOperator(Operator :STRING):StringArray; var i:INTEGER; begin k:= 0; for i := 1 to Length(Operator) do begin if not(Operator[i] = '|') then begin
if Operator[i] = '|' then begin inc(k); end else begin inc(k); if (Operator[i]= '*') or (Operator[i] = '/') then begin vFeld[k] := '('; inc(k); vFeld[k] := Operator[i]; inc(k); vFeld[k] := ')'; end else begin vFeld[k] := Operator[i]; end; end; end; end; result := vFeld; end; |
|
|
Xardas008 
      
Beiträge: 149
Win 7 Professional x64, Ubuntu 10.04, Windows Server 2008 R2
C#, Visual Studio 2008 Pro, Visual Studio 2010 Ultimate, Eclipse (Java)
|
Verfasst: Do 29.03.07 14:50
Habe folgende Schleife gebastelt, funktioniert fast, wenige Stellen erhalten einen falschen Wert. Hier die Schleife:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
| for i:= 1 to Length(Operator) do begin if (Operator[i] = '(') then begin for k := 1 to Length(Operator) do begin dummy3[k] := 0; end; for k:=i to Length(Operator) do begin dummy3[k] := vNumber[k+2]; end; for k:=i to Length(Operator) do begin vNumber[k+3] := dummy3[k]; end;
end else begin if (Operator[i] = ')') then begin for k:= 1 to Length(Operator) do begin dummy3[k] := 0; end; for k:= i to Length(Operator) do begin dummy3[k] := vNumber[k]; end; for k:=i to Length(Operator) do begin vNumber[k+1] := dummy3[k]; end;
end; end; |
Bei der Beispielrechnung 1+ (2x3) - (1/2) + 6 muss die zweite 1 an Position 5 (von Pos. 4) und die 6 auf Pos. 9 von Pos. 6, an Pos. 5 landet die 1 auch, Pos. 9 erhält auch die 6, nur Position 6 erhält auch die 1, obwohl hier die 2 hingehört und pos. 7 hat dann die 2, die aber beim Rechnen nicht beachtet wird, da an der Stelle ein Operator steht der nicht abgefragt wird da es ne Klammer ist.
Am besten baue ich euch mal die Arrays hier auf.
Operator{'+','(','*',')','-','(','/',')','+',' ',...}
vNumber{1,2,3,4,5,6,0...}
Ist ziemlich kompliziert, gebe ich zu.
Wenn ihr noch Infos braucht, einfach sagen, ich bemüh mich dann diese zu liefern.
|
|
jaenicke
      
Beiträge: 19336
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 29.03.07 16:00
Also ich werd mir das mal ansehen, aber was ich mich frage ist: Warum so kompliziert?
IMHO ist es deutlich einfacher eine Baumstruktur zu verwenden. So habe ich das auch gemacht, als ich symbolische Berechnungen durchführen wollte. Ganz nebenbei ist es so relativ einfach auch Ableiten und Integrieren einzubauen (naja Integrieren ist noch nicht fertig...).
Aber das wollte ich nur mal anmerken, deine Lösung werde ich mir mal ansehen, der Fehler muss ja zu finden sein.
|
|
Xardas008 
      
Beiträge: 149
Win 7 Professional x64, Ubuntu 10.04, Windows Server 2008 R2
C#, Visual Studio 2008 Pro, Visual Studio 2010 Ultimate, Eclipse (Java)
|
Verfasst: Do 29.03.07 17:15
Von Baumstruktur habe ich bisher noch nichts gehört, ka wie die gehen soll. Ich weiß ich programmiere irgendwie immer etwas zu kompliziert, sodass ich meistens später nicht mehr weiß was ich grade überhaupt gemacht habe lol^^
|
|
Xardas008 
      
Beiträge: 149
Win 7 Professional x64, Ubuntu 10.04, Windows Server 2008 R2
C#, Visual Studio 2008 Pro, Visual Studio 2010 Ultimate, Eclipse (Java)
|
Verfasst: Fr 30.03.07 08:48
Wo kann ich etwas über diese Baumstruktur nachlesen, vielleicht bekomme ich das Problem damit eher gelöst.
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Fr 30.03.07 10:46
Moin!
Eine weitere, weit verbreitete Methode, die Operatorenrangfolge abzubilden, ist ein (Calculator-)Stack, also ein Kellerspeicher. Schau mal, ob du damit und geeigneten eigenen Klassen für Operatoren, die du dann mit den Argumenten in den Stack packst, weiter kommst.  Zumindest der Stack (= TStack) ist schon bei Delphi dabei.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Xardas008 
      
Beiträge: 149
Win 7 Professional x64, Ubuntu 10.04, Windows Server 2008 R2
C#, Visual Studio 2008 Pro, Visual Studio 2010 Ultimate, Eclipse (Java)
|
Verfasst: Fr 30.03.07 15:07
So hab die letzten 15 Min nochmal rumexperimentiert, bis zu einer bestimmten Anzahl von Operatoren geht es gut, also oben genanntes Rechenbeispiel löst er nun richtig, aber kommt ein *2 am Ende dazu, gehts schief, dann haben wir eine Abweichung von 2, weil er statt der 6 an Pos. 10 eine 2 stehen hat.
Wie würde oben genanntes Beispiel als Baumstruktur gelöst? Oder wie kann man das sonst lösen dass der Array richtig zugeordnet wird?
|
|
Xardas008 
      
Beiträge: 149
Win 7 Professional x64, Ubuntu 10.04, Windows Server 2008 R2
C#, Visual Studio 2008 Pro, Visual Studio 2010 Ultimate, Eclipse (Java)
|
Verfasst: Mo 02.04.07 06:51
Das Problem ist immer noch nicht gelöst.
|
|
Xardas008 
      
Beiträge: 149
Win 7 Professional x64, Ubuntu 10.04, Windows Server 2008 R2
C#, Visual Studio 2008 Pro, Visual Studio 2010 Ultimate, Eclipse (Java)
|
Verfasst: Di 03.04.07 06:30
So, hab das Problem mal auf eine andere Weise gelöst, nur an einer Stelle hapert es irgendwie, wodurch eine Endlosschleife endsteht.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| while s > 0 do begin term_str := copy(Input, s+1,pos(copy(Input, s+1, length(Input)), ')')-1); erg := GetResult(term_str); Input := copy(Input, 0, s-1)+ erg + copy(Input,s+1, pos(copy(Input, s+1, length(Input)), ')')+1); s := Get_Pos_In_Str(Input, s, Ebene); end; |
term_str soll bei folgendem Beispiel: 1+(2*3-(1+2))die innerste Klammer nehmen, und den Teilstring 1+2 in den term_str kopieren, nur irgendwie kopiert er dort nur einen Leeren String rein, obwohl er bei Get_Pos_In_Str die richtige Position bekommt. Warum????
|
|
|