Autor Beitrag
Xardas008
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
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)
BeitragVerfasst: 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.

ausblenden volle Höhe Delphi-Quelltext
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..40of 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
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)
BeitragVerfasst: Do 29.03.07 14:50 
Habe folgende Schleife gebastelt, funktioniert fast, wenige Stellen erhalten einen falschen Wert. Hier die Schleife:
ausblenden volle Höhe Delphi-Quelltext
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19336
Erhaltene Danke: 1751

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
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)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
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)
BeitragVerfasst: Fr 30.03.07 08:48 
Wo kann ich etwas über diese Baumstruktur nachlesen, vielleicht bekomme ich das Problem damit eher gelöst.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: 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. :idea:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Xardas008 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
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)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
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)
BeitragVerfasst: Mo 02.04.07 06:51 
Das Problem ist immer noch nicht gelöst.
Xardas008 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
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)
BeitragVerfasst: 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.

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