Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Problem mit Mathe-Parser (https://www.delphipraxis.net/142578-problem-mit-mathe-parser.html)

athomas 30. Okt 2009 15:52


Problem mit Mathe-Parser
 
Hallo zusammen,

ich sitz hier vor nem kleinen problem mit einem formelparser.
ich hab ne prozedur geschrieben, die einen klammerfreien ausdruck zerstückelt in zahlen und operatoren.
eine weitere prozedur soll dieses array in ne gleitkommazahl umwandeln. klappt soweit auch ganz gut, nur wenn ich ein negatives vorzeichen hab bekomm ich den fehler, dass der index das maximum meiner tstringlist überschreiten würde.
kann sich das bitte mal jemand ansehen :)

Delphi-Quellcode:
function arrBerechnen(s: TStringlist): real;
var
  i, j: integer;
  arr: TStringlist;
  ende: boolean;
begin
  arr:=TStringlist.create();
  arr.clear;
  arr:=s;

  //Produkt
  ende:=false;
  i:=1;
  if arr.count>1 then
    begin
      while not(ende) do
        begin
          if (arr[i]='*') then
            begin
              arr[i-1]:=floattostr(strtofloat(arr[i-1])*strtofloat(arr[i+1]));
              arr.delete(i);
              arr.delete(i);
            end;
          ende:=true;
          for j:=0 to arr.count-1 do
            if arr[j]='*' then
              ende:=false;    
          i:=i+1;
          i:=i mod (arr.count);
        end;
    end;
   
  //Quotient
  ende:=false;
  i:=1;
  if arr.count>1 then
    begin
      while not(ende) do
        begin
          if (arr[i]='/') then
            begin
              arr[i-1]:=floattostr(strtofloat(arr[i-1])/strtofloat(arr[i+1]));
              arr.delete(i);
              arr.delete(i);
            end;
          ende:=true;
          for j:=0 to arr.count-1 do
            if arr[j]='/' then
              ende:=false;    
          i:=i+1;
          i:=i mod (arr.count);
        end;
    end;
       
  //Differenz
  ende:=false;
  i:=1;
  if arr.count>1 then
    begin
      while not(ende) do
        begin
          if (arr[i]='-') then
            begin
              if i=1 then
                begin
                  arr[i-1]:=floattostr(- strtofloat(arr[i]));
                  arr.delete(i);
                end
              else
                begin
                  arr[i-1]:=floattostr(strtofloat(arr[i-1])-strtofloat(arr[i+1]));
                  arr.delete(i);
                  arr.delete(i);
                end;
            end;
          ende:=true;
          for j:=0 to arr.count-1 do
            if (arr[j]='-')and(length(arr[j])=1) then
              ende:=false;
          i:=i+1;
          i:=i mod (arr.count);
        end;
    end;
  //Summe
  ende:=false;
  i:=1;
  if arr.count>1 then
    begin
      while not(ende) do
        begin
          if (arr[i]='+') then
            begin
              arr[i-1]:=floattostr(strtofloat(arr[i-1])+strtofloat(arr[i+1]));
              arr.delete(i);
              arr.delete(i);
            end;
          ende:=true;
          for j:=0 to arr.count-1 do
            if arr[j]='+' then
              ende:=false;
          i:=i+1;
          i:=i mod (arr.count);
        end;
    end;
 
  result:=strtofloat(arr[0]);
  arr.free;
end;

himitsu 30. Okt 2009 16:10

Re: Problem mit Mathe-Parser
 
Zitat:

Delphi-Quellcode:
arr:=s;

hier überschreibst du die vorher etstelle Instant der Stringliste!
richtiger wäre:
Delphi-Quellcode:
arr.Assign(s);
PS: TStrings als Parameter macht sich besser (so kann man auch StringList-ähnliche Dinge übergeben
(z.B. Memo1.Lines , welches ich für meinen Test mal schnell genommen hab)


Zitat:

Delphi-Quellcode:
if i=1 then

das Minus ist ja wohl im Index 0 :zwinker:
Zitat:

Delphi-Quellcode:
for j:=0 to arr.count-1 do
...
i:=i mod (arr.count);

setzt i auf 0 und führt die While-Schleite nochmals ab 0 aus
PS: fange gleich mit i:=0; an (bei + und -), dann muß da nicht doppelt bearbeitet werden


PS: das + gibt es auch als Vorzeichen (hast du ganz vergessen)
PSS: + und - als Vorzeichen innerhalb eines Strings "1+-2" dürfte auch Probleme bereiten

athomas 30. Okt 2009 16:32

Re: Problem mit Mathe-Parser
 
danke schonmal für die schnelle antwort

ich hab deine tipps befolgt und die while-schleife von null gestartet:
Delphi-Quellcode:
//Differenz
  ende:=false;
  i:=0;
  if arr.count>1 then
    begin
      while not(ende) do
        begin
          if (arr[i]='-') then
            begin
              if i=0 then
                begin
                  arr[i]:=floattostr(- strtofloat(arr[i+1]));
                  arr.delete(i+1);
                end
              else
                begin
                  arr[i-1]:=floattostr(strtofloat(arr[i-1])-strtofloat(arr[i+1]));
                  arr.delete(i);
                  arr.delete(i);
                end;
            end;
          ende:=true;
          for j:=0 to arr.count-1 do
            if (arr[j]='-')and(length(arr[j])=1) then
              ende:=false;
          i:=i+1;
          i:=i mod (arr.count);
        end;
    end;
negative vorzeichen funktionieren jetzt soweit ganz gut, aber wenn ich z.b. -1-2-3-4-5 eingebe, konnt -7 raus ^^
was stimmt denn noch nicht

himitsu 30. Okt 2009 16:42

Re: Problem mit Mathe-Parser
 
nimm mal arr.Text in die Liste der überwachten Ausdrücke (Strg+Alt+W) auf,
setze einen Haltepunkt (F5) vor diese Schleife und geh dann ab dort die Schleife mal im Einzelschritt (F7) durch

in der Liste kannst du dann schrittweise beobachten, was mit deinem arr passiert


PS: wenn arr.Text zu unübersichtlich ist, dann kann man auch dieses in diese Liste aufnehmen
(Funktionsaufrufe natürlich gestatten)
Code:
StringReplace(arr.Text, sLineBreak, ' | ', [rfReplaceAll])
und wenn es heißt "Funktion wurde vom Compiler entfernt", dann noch irgendwo im QuellText diese Funktion verwenden
z.B. einfach irgendwo StringReplace('','','',[]); einfügen (zwar voll sinnlos, aber nun ist diese Funktion vorhanden :stupid: )

[add]
mach aus diesem
Delphi-Quellcode:
i:=i+1;
i:=i mod (arr.count);
einfach nur
Delphi-Quellcode:
i:=0;
der Grund ist, daß so die Werte in der falschen Reihenfolge aufgelöst werden
-1-2-3-4-5 und dein Code macht ((-1)-2)-(3-4)-5

athomas 30. Okt 2009 17:17

Re: Problem mit Mathe-Parser
 
wenn ich doch aber
Delphi-Quellcode:
i:=i+1;
i:=i mod (arr.count);
mit i:=0 ersetze komm ich in ne endlos-schleife, oder hab ich dich falsch verstanden?

ach ja, das problem mit -- oder +- hab ich einfach mit stringreplace lösen können :)

aber was mir noch aufgefallen ist: x*(-4) oder x/(-4) funktioniert auch nicht

Namenloser 30. Okt 2009 17:31

Re: Problem mit Mathe-Parser
 
Zitat:

Zitat von athomas
ach ja, das problem mit -- oder +- hab ich einfach mit stringreplace lösen können :)

Was gar nicht nötig wäre, weil das kein korrekter mathematischer Ausdruck ist. :wink:

himitsu 30. Okt 2009 17:33

Re: Problem mit Mathe-Parser
 
theoretisch nicht,

aber nachdem
> - 1 - 2 - 3 - 4 - 5
bis hier aufgelöst wurde
> -3 - 3 - 4 - 5
hier nach ist i nun 1
und es wird grad noch das - getroffen
> -6 - 4 - 5
danach steht i durch deine Berechnung aber auf 2,
verfehlt knapp das 1. "-" und nimmt sich als Nächstes erstmal das 2. "-" vor, also 4 - 5
> -6 - -1
und im letzten Durchgang kommt es dann natürlich zu
> -7

stimmt ... die Endlosschleife hab ich glatt übersehn
versuch mal nur i:=i+1; an dieser Stelle und wenn du was ersetzt hast, dann ma da gleich ein i:=i-1; oder i:=-1; rein :gruebel:

Zitat:

Zitat von athomas
ach ja, das problem mit -- oder +- hab ich einfach mit stringreplace lösen können :)

man hätte auch statt i=0 auf "ist davor nichts oder noch ein anderer Operator (+-*/)" bzw. "ist davor KEINE Zahl" prüfen können.
denn wenn dieses zutrifft, dann handelt es sich bei diesem + oder - um ein Vorzeichen ... ansonsten um einen Operator

@NamenLozer:
1--2 aka 1 - -2 ist also nicht korrekt?

athomas 30. Okt 2009 17:42

Re: Problem mit Mathe-Parser
 
stimmt ja, hab ich wohl übersehen: wenn ich die funktion delete aufrufe verschiebt sich ja das ganze array

also das addieren und subtrahieren funktioniert jetzt, aber ich hab jetzt ein problem beim multiplizieren mit negativen zahlen:

Delphi-Quellcode:
//Produkt
  ende:=false;
  i:=1;
  if arr.count>1 then
    begin
      while not(ende) do
        begin
          if (arr[i]='*') then
            begin
              arr[i-1]:=floattostr(strtofloat(arr[i-1])*strtofloat(arr[i+1]));
              arr.delete(i);
              arr.delete(i);
              i:=i-2;
            end;
          ende:=true;
          for j:=0 to arr.count-1 do
            if arr[j]='*' then
              begin
                ende:=false;
                break;
              end;
          i:=i+1;
        end;
    end;
wenn ich -2 * -2 rechne gibt er mir -2 aus, als ob er -* als einen unbekannten operator ansehen würde

Namenloser 30. Okt 2009 17:46

Re: Problem mit Mathe-Parser
 
Zitat:

Zitat von himitsu
@NamenLozer:
1--2 aka 1 - -2 ist also nicht korrekt?

Ja. Bei so etwas sind Klammern nötig: Nur 1-(-2) ist formal korrekt.

athomas 30. Okt 2009 17:54

Re: Problem mit Mathe-Parser
 
war auch mein erster gedanke:
(-2)*(-2) kommt aber auch -2 raus


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:10 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz