Avatar billede jetzen Nybegynder
17. december 2004 - 08:50 Der er 13 kommentarer

Hurtige point - lommeregner

Jeg har en streng med forskellige tal og regneopperatorer

fx: disp:="2232*343+123-12"

hvordan får kan jeg få delphi til at beregne resultatet.

Går ud fra at jeg skal opdele strengen...
Avatar billede arne_v Ekspert
17. december 2004 - 08:57 #1
Hvis du vil gøre det generelt (med support for parenteser etc.) så kræver det en
del kode.

Men måske kan du finde noget på nettet.

Søg på expression evaluation.

Teknikken er kendt:
  - parse streng til symbolsk form
  - konverter fra infix til postfix
  - beregn
Avatar billede pellelil Nybegynder
17. december 2004 - 11:06 #2
Sammen med PolyPascal (ja det var tider <G>), var bl.a. souce til en Parser, som jeg selv har brugt et par gange (ja selv i dag i Delphi), så med mindre du lige har en PolyPascal liggende ved siden af din PC, vil jeg forsøge at grave soucen frem fra mine gemmer.
Avatar billede hestetoften Nybegynder
17. december 2004 - 12:04 #3
prøv med denne:

disp:=(((2232*343)+123)-12);
Avatar billede hestetoften Nybegynder
17. december 2004 - 12:06 #4
Husk at tallene og "disp" ikke skal være strings, men integer

hvis disp er en string så brug: disp:=intToStr(((2232*343)+123)-12);
Avatar billede tolderlund Nybegynder
17. december 2004 - 12:21 #5
Download Turbopowers SysTools fra
http://sourceforge.net/projects/tpsystools/
Den indeholder mange gode ting, bl.a. en expression evaluator (TStExpression).
Så kan du gøre sådan:
var
  i: Integer;
begin
  StExpression1.Expression := '2232*343+123-12';
  i := StExpression1.AsInteger;
  Edit1.Text := IntToStr(i);
  {eller}
  Edit2.Text := StExpression1.AsString;
{=765687}
Avatar billede stefmeister Nybegynder
19. december 2004 - 02:10 #6
Det er meget besværligt, ikke noget man bare gør. Har selv forsøgt mange gange.
Hvis det skal virke ordenligt, så skal man hente komponenter etc. Hvilket jeg selv synes er lidt trist, da man så ikke "selv" har lavet programmet.
Avatar billede arne_v Ekspert
19. december 2004 - 18:22 #7
Man kan sagtens lave det uden komponenter.

Enhver datalogi studerende bør kunne lave et sådant program.

Men det kræver en smule kode.

Jeg har lavet det en gang i Fortran og en gang i C++.
Avatar billede jetzen Nybegynder
19. december 2004 - 20:29 #8
Hm.
Det lader til der er en del uenighed på området.

Overvejede om det ikke kunne lade sig gøre at opdele strengen i forskellige variabler, og der efter lave noget if() men regne opperatoren, men da jeg ikke er så programmeringskyndig vil jeg gerne have lidt bud.

Har ikke den store lyst til bareat smide en komponent ind, da jeg som stefmeister
antyder ikke selvhar lavet programmet.
Avatar billede arne_v Ekspert
19. december 2004 - 20:40 #9
Problemet med if og copy er et det er nok nemt med de helt simple
eksempler men det bliver hurtigt til noget spagetti når man skal have styr
på det hele:
  - brug af parenterser
  - operator precedence
Avatar billede arne_v Ekspert
19. december 2004 - 20:41 #10
Jeg har iøvrigt den sidste af de 3 pinde liggende i Pascal/Delphi !
Avatar billede pellelil Nybegynder
20. december 2004 - 09:26 #11
Vedlagte kode er som nævnt oprindelig fra PolyPascal (så det er måske Anders selv der har skrevet det <G>) og som du kan se i
Kommentaren fik jeg "et sjovt problem" da jeg skulle anvende den i Delphi 3, og var derfor nødt til at omskrive den lidt (måske ikke længere nødvendigt). Den nederste funktion ("Calc") kan du ikke anvende som den er, men du kan bruge den som et eksempel på hvordan man kan lave en "wrapper" til Evaluate funktionen (I Calc fjerner jeg alle mellemrum, og laver "," om til ".", samt håndtere evt. Division Zero).

<SNIP>
Procedure Evaluate(Var szExpr : String; Var fltValue : Float; Var iErrPos : integer);
type
  stdf = (fabs,fsqrt,fsin,fcos,farctan,fln,fexp);
  stdflist = array[stdf] of string[6];
const
  stdfun : stdflist = ('ABS','SQRT','SIN','COS','ARCTAN','LN','EXP');
  chErr    = '?';
  chEofLine = #13;
var
  iPos : integer;
  ch  : char;

  Procedure  NextChar;
  begin
    repeat
      iPos := iPos + 1;
      if iPos <= length(szExpr) then ch := szExpr[iPos]
                                else ch := chEofLine;
    until ch <> ' ';
  end;

  Function  Expression : Float;
  var
    E  : Float;
    Opr : char;

    Function  Simexpr : Float;
    var
      s  : Float;
      opr : char;

      Function  Term : Float;
      var
        t : Float;

        Function  Signedfactor : Float;

          Function  Factor : Float;
          {Delphi 3.0 gives Internal Error: URW376  (Moved to outer function)
          type
            stdf = (fabs,fsqrt,fsin,fcos,farctan,fln,fexp);
            stdflist = array[stdf] of string[6];
          const
            stdfun : stdflist = ('ABS','SQRT','SIN','COS','ARCTAN','LN','EXP');
          }
          var
            p,e,sl : integer;
            found  : boolean;
            f      : Float;
            sf    : stdf;
          begin
            if ch in ['0'..'9'] then begin
              p := iPos;
              repeat NextChar until not(ch in ['0'..'9','.'{DecimalSeparator}]);
              if ch in ['E','e'] then begin
                NextChar;
                if ch in ['+','-'] then NextChar;
                while ch in ['0'..'9'] do NextChar;
              end;
              val(copy(szExpr, p, iPos-p), f, e);
              if e<>0 then begin
                iPos := p + e - 1;
                ch := chErr;
              end;
            end else
            if ch='(' then begin
              NextChar;
              f := expression;
              if ch = ')' then NextChar
                          else ch := chErr;
            end else
            if ch='X' then begin
              NextChar;
              f := fltValue;
            end else begin
              found := false;
              for sf := fabs to fexp do begin
                if not found then begin
                  sl := length('stdfun[sf]');
                  if copy(szExpr, iPos, sl) = 'stdfun[sf]' then begin
                    iPos := iPos + sl - 1;
                    NextChar;
                    f := factor;
                    case sf of
                      fabs    : f := abs(f);
                      fsqrt  : f := sqrt(f);
                      fsin    : f := sin(f);
                      fcos    : f := cos(f);
                      farctan : f := arctan(f);
                      fln    : f := ln(f);
                      fexp    : f := exp(f);
                    end;
                    found := true;
                  end;
                end;
              end;
              if not found then ch := chErr;
            end;
            factor := f;
          end;

        begin
          if ch = '-' then begin
            NextChar;
            signedfactor := -factor;
          end else begin
            signedfactor := factor;
          end;
        end;

      begin
        t := signedfactor;
        while ch = '^' do begin
          NextChar;
          t := exp(ln(t)*signedfactor);
        end;
        term := t;
      end;

    begin
      s := term;
      while ch in ['*','/'] do begin
        opr := ch;
        NextChar;
        case opr of
          '*' : s:=s*term;
          '/' : begin
                  TempFloat := term;
                  S := S / TempFloat;
                end;
        end;
      end;
      simexpr := s;
    end;

  begin
    e := simexpr;
    while ch in ['+','-'] do begin
      opr := ch;
      NextChar;
      case opr of
        '+' : e := e + simexpr;
        '-' : e := e - simexpr;
      end;
    end;
    expression := e;
  end;

begin
  iPos := 0;
  nextchar;
  fltValue := expression;
  if (ch = chEofLine) then iErrpos := 0
                      else iErrpos := iPos;
end;


Function  Calc(szExpression : String) : Float;
var
  fltRes    : Float;
  iErrorPos : Integer;
begin
  Try
    szExpression := StripCh(szExpression, ' ');
    szExpression := ReplaceCh(szExpression, ',', '.');
    Evaluate(szExpression, fltRes, iErrorPos);
    Result := fltRes;
    if iErrorPos <> 0 then fltRes := 0;
  Except
    On EZeroDivide do Result := 0;
  end;
end;
</SNIP>
Avatar billede tolderlund Nybegynder
20. december 2004 - 11:52 #12
Det er måske udemærket at man vil lave det selv, i stedet for at bruge en komponent. Men så skal man da ikke spørge her, for så har man jo ikke lavet det selv?!?!
Om man bruger en komponent som en anden har lavet eller bruger en procedure som en anden har lavet, hvad forskel gør det??
Der er vist noget her som jeg ikke forstår. Oh well ...
Avatar billede stefmeister Nybegynder
20. december 2004 - 13:31 #13
tolderlund -> hvis man får hjælp herinde, så kan man oftest spørge personen der har lavet det, om hvad der sker etc. plus det er nemmere selv at rette i koden. Hvis man bruger en komponent, så synes jeg ofte det er en masse mærkelige ting i koden, ofte mere end der egenlig er nødvendigt.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester