To the main page
As a rule it's convenient to convert any arithmetical expression to the
Postfix Polish Notation (PPN) in order to get rid of brackets
contained in the expression. You can calculate expressions converted to
PPN from left to right consistently.
There are two well known ways to convert an expression to PPN. Let's
consider each of them:
1. The converting to PPN by
means of the stack
We'll need a stack for variables which have char type because we get the origin
expression as a string.
Let's consider each symbol consistently. There can be 4 possible
situations:
1. The symbol is a number (or a variable). Then we just put it to our
output string.
2. The symbol is a operation sign (such as: +, -, *, / ). Then we check
the priority of the operation. The multiplication and the division have
got the highest priority (3). The addition and the subtraction have got
lower priority (2). An opening bracket has got the lowest priority (1).
When we've received one of these symbols we have to check the stack:
a) if the stack is empty or there are
only symbols which priority is lower than the current symbol's priority
there then we put the current symbol to the stack.
b) if the priority of the symbol disposed on the top of the stack is
greater or equal to priority of the current symbol we take out symbols
from the stack until this condition is broken; then we pass to the
point a).
3. If the current symbol is an opening bracket we put it to the stack.
4. If the current symbol is a closing bracket we take out symbols from
the stack until we find an opening bracket there (it must be a symbol
with the priority 1); then we just destroy the opening bracket we've
found. The closing bracket must be destroyed too.
If we've analysed all input string but there are still some symbols in
the stack we have to take out and put them to the output string.
Let's consider one simple example:
The origin expression is a + ( b - c ) * d
Let's consider each symbol:
Symbol
Action
The
output string after this action
The stack
after this action
a
'a' is a variable. We must put
it to the output string
a
empty
+
'+' is a sign of operation. We
put it to the stack (stack is still empty so we needn't check the
symbol's priority)
a
+
(
'(' is an opening bracket. We
put it to the stack.
a
+ (
b
'b' is a variable. We must put
it to the output string
a b
+ (
-
'-' is a sign of operation. Its
priority is 2. Now we must check the stack. There is '(' on the top of
the stack. Its priority is 1. So we must put the current '-' symbol to
the stack.
a b
+ ( -
c
'c' is a variable. We must put
it to the output string
a b c
+ ( -
)
')' is a closing bracket. We
must take out symbols from the stack till we find an opening bracket.
Then we destroy both brackets.
a b c -
+
*
'-' is a sign of operation. Its
priority is 3. We must check the stack: there is a '+' symbol on the top
of the stack. Its priority is 2 and less than the priority of the '*'
symbol. So we just put the current '*' symbol to the stack.
a b c -
+ *
d
'd' is a variable. We must put
it to the output string
a b c - d
+ *
Now we've parsed all the input string but there're still signs of
operation in the stack. We must take them out and put them to the output
string. Since the stack is a structure organized in according to the
LIFO principle we take out the '*' symbol at first and then we take out
the '+' symbol.
So we have got the final result: a b c - d * +
Download the implementation of the algorithm.
This algorithm is also used in the Calc3 program disposed here (see the file named CPPNCalc.cpp).
2. The converting to PPN by means of the
recursive descent
The implementation of this algorithm is several functions which call
each other consistently.
The converting begins calling the begin() function which handles the
addition and the subtraction (it stores signs of these operations in
temporary variables and puts them to the output string when receives the
management again).
The begin() function calls the mult_div() function handling the
multiplication and the division (it stores signs of these operations in
temporary variables and puts them to the output string when receives the
management again)..
Then mult_div() function calls the symbol() function handling numbers
(or variables) and brackets. If the symbol() function receives an
opening bracket it calls the begin() function once more and then expects
a closing bracket when receives the management again. If it doesn't
receive a closing bracket there is some error in the expression.
If the symbol() function receives a variable it puts that variable to
the output string.
The implementation in C++ (classes from the VCL were used for working
with strings and exceptions):
class TStr2PPN { AnsiString instr, outstr; //input & output strings char curc; //the current character int iin; //the index of the input string
char nextChar(); //get the next character void begin(); //handle plus & minus void mult_div(); //handle multiplication & division void symbol(); //handle characters
public: TStr2PPN() { //constructor iin = 1; }
void convert(char *str); //convert to PPN AnsiString get_outstr(); //get the output string };
//get the next character inline char TStr2PPN::nextChar() { if(iin <= instr.Length()) return curc = instr[iin++]; return curc = '\0'; }
//get the output string inline AnsiString TStr2PPN::get_outstr(){return outstr;}
3. The algorithm of the
calculation of the expression written in PPN
We'll use the stack for numbers (or for variables if there are some).
The algorithm is very simple. Now our input string is the expression
written in PPN:
1. If the current symbol is a number we put it to the stack.
2. If the current symbol is any operation sign we have to take out two
numbers from the stack and use them as operands for that operation and
then put the result to the stack.
When we've analysed all input string there must be one number in the
stack. And this number is a result of our calculation.
Let's consider one simple example:
The origin expression is 7 5 2 - 4 * +
Let's consider each symbol:
Symbol
Action
The stack
after this action
7
'7' is a number. We put it to
the stack.
7
5
'5' is a number. We put it to
the stack.
7 5
2
'2' is a number. We put it to
the stack.
7 5 2
-
'-' is a sign of operation. We
have to take out two numbers (5 and 2) from the stack and implement the
5 - 2 = 3 operation. Then we put the result to the stack.
7 3
4
'4' is a number. We put it to
the stack.
7 3 4
*
'*' is a sign of operation. We
have to take out two numbers (3 and 4) from the stack and implement the
3 * 4 = 12 operation. Then we put the result to the stack.
7 12
+
'+' is a sign of operation. We
have to take out two numbers (7 and 12) from the stack and implement the
7 + 12 = 19 operation. Then we put the result to the stack.
19
Now we've parsed all the input string and there's one number in the
stack. This number is a result of our calculation.
The implementation in C++:
int calculate(string str_in) { Stack<int> val_stack; //stack int n1, n2, res;
for(i = 0; i<str_in.length(); ++i) { if(isNumber(str_out[i])) { val_stack.push(str_out[i]); } else { n2 = val_stack.pop(); n1 = val_stack.pop(); switch(str_out[i]) { case '+': res = n1 + n2; break; case '-': res = n1 - n2; break; case '*': res = n1 * n2; break; case '/': res = n1 / n2; break; default: cout<<"Error !\n"; } val_stack.push(res); } } return val_stack.pop(); }
This algorithm is also used in the Calc3 program disposed here (see the file named CPPNCalc.cpp).