[Back to MATH SWAG index] [Back to Main SWAG index] [Original]
{
THAI TRAN
{
I've netmailed you the full-featured version (800 lines!) that will do
Functions, exponentiation, factorials, and has all the bells and whistles,
but I thought you might want to take a look at a simple version so you can
understand the algorithm.
This one only works With +, -, *, /, (, and ). I wrote it quickly, so it
makes extensive use of global Variables and has no error checking; Use at
your own risk.
Algorithm to convert infix to postfix (RPN) notation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Parse through the entire expression getting each token (number, arithmetic
operator, left or right parenthesis). For each token, if it is:
1. an operand (number) Send it to the RPN calculator
2. a left parenthesis Push it onto the operator stack
3. a right parenthesis Pop operators off stack and send to RPN
calculator Until the a left parenthesis is
on top of the stack. Pop it also, but don't
send it to the calculator.
4. an operator While the stack is not empty, pop operators
off the stack and send them to the RPN
calculator Until you reach one With a higher
precedence than the current operator (Note:
a left parenthesis has the least precendence).
Then push the current operator onto the stack.
This will convert (4+5)*6/(2-3) to 4 5 + 6 * 2 3 - /
Algorithm For RPN calculator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note: this Uses a different stack from the one described above.
In RPN, if an operand (a number) is entered, it is just pushed onto the
stack. For binary arithmetic operators (+, -, *, /, and ^), the top two
operands are popped off the stack, operated on, and the result pushed back
onto the stack. if everything has gone correctly, at the end, the answer
should be at the top of the stack.
Released to Public Domain by Thai Tran (if that matters).
}
{$X+}
Program Expression_Evaluator;
Const
RPNMax = 10; { I think you only need 4, but just to be safe }
OpMax = 25;
Type
String15 = String[15];
Var
Expression : String;
RPNStack : Array[1..RPNMax] of Real; { Stack For RPN calculator }
RPNTop : Integer;
OpStack : Array[1..OpMax] of Char; { Operator stack For conversion }
OpTop : Integer;
Procedure RPNPush(Num : Real); { Add an operand to the top of the RPN stack }
begin
if RPNTop < RPNMax then
begin
Inc(RPNTop);
RPNStack[RPNTop] := Num;
end
else { Put some error handler here }
end;
Function RPNPop : Real; { Get the operand at the top of the RPN stack }
begin
if RPNTop > 0 then
begin
RPNPop := RPNStack[RPNTop];
Dec(RPNTop);
end
else { Put some error handler here }
end;
Procedure RPNCalc(Token : String15); { RPN Calculator }
Var
Temp : Real;
Error : Integer;
begin
Write(Token, ' '); { This just outputs the RPN expression }
if (Length(Token) = 1) and (Token[1] in ['+', '-', '*', '/']) then
Case Token[1] of { Handle operators }
'+' : RPNPush(RPNPop + RPNPop);
'-' : RPNPush(-(RPNPop - RPNPop));
'*' : RPNPush(RPNPop * RPNPop);
'/' :
begin
Temp := RPNPop;
if Temp <> 0 then
RPNPush(RPNPop/Temp)
else { Handle divide by 0 error }
end;
end
else
begin { Convert String to number and add to stack }
Val(Token, Temp, Error);
if Error = 0 then
RPNPush(Temp)
else { Handle error }
end;
end;
Procedure OpPush(Operator : Char); { Add an operator onto top of the stack }
begin
if OpTop < OpMax then
begin
Inc(OpTop);
OpStack[OpTop] := Operator;
end
else { Put some error handler here }
end;
Function OpPop : Char; { Get operator at the top of the stack }
begin
if OpTop > 0 then
begin
OpPop := OpStack[OpTop];
Dec(OpTop);
end
else { Put some error handler here }
end;
Function Priority(Operator : Char) : Integer; { Return priority of operator }
begin
Case Operator OF
'(' : Priority := 0;
'+', '-' : Priority := 1;
'*', '/' : Priority := 2;
else { More error handling }
end;
end;
Procedure Evaluate(Expr : String); { Guess }
Var
I : Integer;
Token : String15;
begin
OpTop := 0; { Reset stacks }
RPNTop := 0;
Token := '';
For I := 1 to Length(Expr) DO
if Expr[I] in ['0'..'9'] then
begin { Build multi-digit numbers }
Token := Token + Expr[I];
if I = Length(Expr) then { Send last one to calculator }
RPNCalc(Token);
end
else
if Expr[I] in ['+', '-', '*', '/', '(', ')'] then
begin
if Token <> '' then
begin { Send last built number to calc. }
RPNCalc(Token);
Token := '';
end;
Case Expr[I] OF
'(' : OpPush('(');
')' :
begin
While OpStack[OpTop] <> '(' DO
RPNCalc(OpPop);
OpPop; { Pop off and ignore the '(' }
end;
'+', '-', '*', '/' :
begin
While (OpTop > 0) AND
(Priority(Expr[I]) <= Priority(OpStack[OpTop])) DO
RPNCalc(OpPop);
OpPush(Expr[I]);
end;
end; { Case }
end
else;
{ Handle bad input error }
While OpTop > 0 do { Pop off the remaining operators }
RPNCalc(OpPop);
end;
begin
Write('Enter expression: ');
Readln(Expression);
Write('RPN Expression = ');
Evaluate(Expression);
Writeln;
Writeln('Answer = ', RPNPop : 0 : 4);
end.
[Back to MATH SWAG index] [Back to Main SWAG index] [Original]