program microcalc; Uses Crt; TYPE Real=Extended; {******** From Turbo-Pascal 3.0 'MICROCALC' (example-program) ************} {******************* !!!!! recursiv !!!!! ********************************} procedure Evaluate(var Formula: String; { Fomula to evaluate} x : Real; { Place for x in formula } var Value: Real; { Result of formula } var ErrPos: Integer); { Position of error } const Numbers: set of Char = ['0'..'9']; EofLine = ^M; var Pos, i: Integer; { Current position in formula } Ch: Char; { Current character being scanned } dummy : String; SumR, SumL : Integer; { Procedure NextCh returns the next character in the formula } { The variable Pos contains the position ann Ch the character } procedure NextCh; begin repeat Pos:=Pos+1; if Pos<=Length(Formula) then Ch:=Formula[Pos] else Ch:=eofline; until Ch<>' '; end { NextCh }; function Fak(I: Integer): Real; { Fakultaet } var dummy : Real; j : Integer; begin IF i=1 THEN BEGIN Fak:=1; Exit; END; dummy:=1; FOR i:=1 TO I DO Dummy:=dummy*i; Fak:=dummy; end { Fact }; function Expression: Real; var E: Real; Opr: Char; function SimpleExpression: Real; var S: Real; Opr: Char; function Term: Real; var T: Real; function SignedFactor: Real; function Factor: Real; type StandardFunction = (fabs,fsqrt,fsqr,fsin,fcos, farctan,fln,flog,fexp,ffact,fPi, fE, fX); StandardFunctionList = array[StandardFunction] of string[6]; const StandardFunctionNames: StandardFunctionList =('ABS','SQRT','SQR','SIN','COS', 'ARCTAN','LN','LOG','EXP','FAK','PI','E','X'); var E,EE,L: Integer; { intermidiate variables } Found:Boolean; F: Real; Sf:StandardFunction; Start:Integer; begin { Function Factor } if Ch in Numbers then begin Start:=Pos; repeat NextCh until not (Ch in Numbers); if Ch='.' then repeat NextCh until not (Ch in Numbers); if Ch='E' then begin NextCh; repeat NextCh until not (Ch in Numbers); end; Val(Copy(Formula,Start,Pos-Start),F,ErrPos); end else if Ch='(' then begin NextCh; F:=Expression; if Ch=')' then NextCh else ErrPos:=Pos; end else begin found:=false; for sf:=fabs to fX do if not found then begin l:=Length(StandardFunctionNames[sf]); if copy(Formula,Pos,l)=StandardFunctionNames[sf] then begin Pos:=Pos+l-1; NextCh; F:=Factor; case sf of fabs: f:=abs(f); fsqrt: f:=sqrt(f); fsqr: f:=sqr(f); fsin: f:=sin(f); fcos: f:=cos(f); farctan: f:=arctan(f); fln : f:=ln(f); flog: f:=ln(f)/ln(10); fexp: f:=exp(f); ffact: f:=fak(trunc(f)); fPi: f:=Pi; fE: f:=Exp(1); fX: f:=X; end; Found:=true; end; end; if not Found then ErrPos:=Pos; end; Factor:=F; end { function Factor}; begin { SignedFactor } if Ch='-' then begin NextCh; SignedFactor:=-Factor; end else SignedFactor:=Factor; end { SignedFactor }; begin { Term } T:=SignedFactor; while Ch='^' do begin NextCh; t:=exp(ln(t)*SignedFactor); end; Term:=t; end { Term }; begin { SimpleExpression } s:=term; while Ch in ['*','/'] do begin Opr:=Ch; NextCh; case Opr of '*': s:=s*term; '/': s:=s/term; end; end; SimpleExpression:=s; end { SimpleExpression }; begin { Expression } E:=SimpleExpression; while Ch in ['+','-'] do begin Opr:=Ch; NextCh; case Opr of '+': e:=e+SimpleExpression; '-': e:=e-SimpleExpression; end; end; Expression:=E; end { Expression }; begin { procedure Evaluate } {--first make the formula a little easier --} dummy:=''; { remove all blanks } FOR i:=1 TO Length(Formula) DO IF Formula[i]<>' ' THEN Dummy:=dummy+Formula[i]; sumr:=0; suml:=0; FOR i:=1 TO Length(dummy) DO { brackets ok ? } CASE dummy[i] OF ',' : dummy[i]:='.'; '(' : Inc(SumR); ')' : Inc(SumL); ELSE dummy[i]:=UpCase(dummy[i]); END; i:=1; repeat Inc(i); IF (dummy[i]='.') AND NOT (dummy[i-1] IN numbers) THEN BEGIN Insert('0',dummy,i); Inc(i); END; until i>=Length(dummy); if dummy[1]='.' then Insert('0',dummy,1); if dummy[1]='+' then delete(dummy,1,1); IF dummy='' THEN BEGIN Value:=0; ErrPos:=-1; Exit; END; IF sumR<>sumL THEN BEGIN Value:=0; ErrPos:=-2; Exit; END; Formula:=Dummy; Pos:=0; NextCh; Value:=Expression; if Ch=EofLine then ErrPos:=0 else ErrPos:=Pos; end { Evaluate }; var Value, x : Real; ErrPos, i : Integer; Formula : String; BEGIN { Main (Example) } ClrScr; Formula:='fak(49)/(fak(49-6)*fak(6))'; Evaluate(Formula, 0, Value, ErrPos); Writeln(Formula,' = ',Value:7:0,' Possibilitys in "German Lotto"'); Formula:='100000^(1/5)*cos(pi)'; Evaluate(Formula, 0, Value, ErrPos); Writeln(Formula,' = ',Value:7:2,''); Writeln; Formula:='exp(cos(-2*Sqr(x) - 4*x+ 3))/(1/(x+0.01))'; FOR i:=0 TO 10 DO BEGIN x:=i*0.1; Evaluate(Formula, x, Value, ErrPos); Writeln('x = ',x:5:1,' ',Formula,' = ',Value:7:3); END; END.