Classic algorithm-arithmetic expression evaluate
Author: Jiang Yong http://www.kipway.com reprinted please keep this line
Expressions are widely used, such as calculation telemetry in the Power Dispatching System and calculation formula of fare types in the station ticket system.
This article describes the algorithm for converting a medium expression to a post expression and a post expression, and provides the implemented C ++ source code. It also provides a rather concise stack C ++ template class.
Converting an infix expression to a suffix expression
To convert an expression from an infix expression to an equivalent expression expressed in a suffix notation, you must understand the priority and associativity of operators. The priority or operator strength determines the order of values. The priority is high.
Operators with lower priority are evaluated first.
If all operators have the same priority, the order of evaluation depends on their combination. The concatenation of operators defines the order (from right to left or from left to right) of operators of the same priority ).
The conversion process includes using the following algorithm to read the operands, operators, and parentheses of the infix expression:
1. Initialize an empty stack and leave the result string variable empty.
2. Read the infix expression from left to right, one character at a time.
3. If the character is an operand, add it to the result string.
4. If the character is an operator, the pop operator pops up until it meets opening parenthesis, a lower-priority operator, or a right-bound symbol with the same priority. Press this operator into the (push) stack.
5. If the character is an open bracket, press it into the stack.
6. If the character is a closed parenthesis (closing parenthesis), all operators will pop up before opening the brackets and add them to the result string.
7. If it reaches the end of the input string, all operators will pop up and be added to the result string.
Suffix expression evaluate
Evaluate a suffix expression is simpler than simply evaluate an infix expression. In a suffix expression, parentheses are not required, and the operator priority is no longer effective. You can use the following algorithm to evaluate the suffix expression:
1. Initialize an empty Stack
2. Read the suffix expression from left to right
3. If the character is an operand, press it into the stack.
4. If the character is an operator, two operands are displayed, perform the appropriate operation, and then press the result into the stack. If you cannot bring up two operands, the syntax of the suffix expression is incorrect.
5. The result is displayed from the stack at the end of the suffix expression. If the suffix expression format is correct, the stack should be empty.
Data Structure
Both algorithms use stacks. Therefore, we first provide a C ++ template class for the stack. This template is indirect and only contains the functions required for expression calculation. Pop push getsize is as follows:
Template <class T, int size> class carraystacktemp
{
Public:
Carraystacktemp () {Top =-1 ;}; // default constructor to construct an empty Stack
~ Carraystacktemp () {}; // destructor
Bool push (t element); // inbound Stack
Bool POP (T & element); // output Stack
Int getsize () {return top + 1 ;}; // obtain the number of elements
PRIVATE:
T buffer [size];
Int top;
};
Template <class T, int size> bool carraystacktemp <t, size>: Push (t element)
{
Top ++;
If (top> size-1) {top --; return false ;}// full
Buffer [Top] = element;
Return true;
}
Template <class T, int size> bool carraystacktemp <t, size >:: POP (T & element)
{
If (Top =-1) return false; // null
Element = buffer [Top];
Top --;
Return true;
}
This article focuses on the principles and implementation, so the following algorithms only include +-*/() processing, and the operands are automatically converted to Double Floating Point Numbers. Is the calculation of the Y = f (x) function, so the expression supports 'X' characters, case-insensitive, such as: Y = (X-5) + 2/(x + 1 ), the following algorithm code calculates the Y value.
Code for converting an infix expression to a suffix expression
Lpctstr lpszs: expression string
Cstring & SZD: Result
Return = 0: OK
Int g_mid2behind (lpctstr lpszs, cstring & SZD) // the center position-> the rear position only supports () +-*/and X variables.
{
Carraystacktemp <char, 256> STK; // Stack
Cstring szs = lpszs, Szt = "";
Szs. trimleft (); szs. trimright (); szs. makeupper (); // uppercase
Int I, Len = szs. getlength ();
Char C, CC, Buf [256];
For (I = 0; I <Len; I ++)
{
C = szs [I];
If (C> '9') & (c! = 'X') return 1; // contains invalid characters
If (C = '') | (C = '/t') | (C = 0x0d) | (C = 0x0a) continue;
Szt + = C;
}
Len = Szt. getlength ();
If (LEN> 255) return 2; // too long
Sprintf (BUF, "% s", Szt );
Buf [Len] = 0;
Char * P = (char *) BUF;
Szt = ""; SZD = "";
Bool Bret;
While (* P! = 0)
{
C = * P;
If (C> = '0') & (c <= '9') | (C = 'X') | (C = '. ') {Szt + = C; P ++; continue ;}
Else
{
If (! Szt. isempty () // operand, added to the result string
{
Len = Szt. getlength ();
For (I = 0; I <Len; I ++) SZD + = Szt [I];
Szt = "";
}
If (C = '+') | (C = '-'))
{
Do
{If (! STK. Pop (CC) CC = 0;
If (CC! = 0) & (CC! = '(') SZD + = cc;
} While (CC! = 0) & (CC! = '('));
If (Cc = '(') STK. Push (CC );
STK. Push (C );
}
Else if (C = '*') | (C = '/'))
{
Do
{If (! STK. Pop (CC) CC = 0;
If (CC! = 0) & (CC! = '(') & (CC! = '+') & (CC! = '-') SZD + = cc;
} While (CC! = 0) & (CC! = '(') & (CC! = '+') & (CC! = '-'));
If (Cc = '(') | (Cc = '-') | (Cc = '+') STK. Push (CC );
STK. Push (C );
}
Else if (C = '(') STK. Push (C );
Else if (C = ')')
{
Do
{If (! STK. Pop (CC) CC = 0;
If (CC! = 0) & (CC! = '(') SZD + = cc;
} While (CC! = 0) & (CC! = '('));
If (Cc = '(') STK. Push (CC );
}
Else return 3; // operator error
}
P ++;
}
If (! Szt. isempty () // operand, added to the result string
{
Len = Szt. getlength ();
For (I = 0; I <Len; I ++) SZD + = Szt [I];
Szt = "";
}
While (STK. getsize ())
{
Bret = STK. Pop (CC );
If (Bret = true) & (CC! = '(') SZD + = cc;
}
Return 0;
}
Suffix expression evaluate code
Lpctstr lpszparse: Post expression
Double xval: Value of variable X
Double * presult: Calculation Result
Returns true if no error occurs.
Bool calbehindparse (lpctstr lpszparse, double xval, double * presult)
{
Char C;
Const char * Pc = lpszparse;
Double V1, V2;
Carraystacktemp <double, 256> STK; // Stack
Cstring Szt = "";
While (* PC! = NULL)
{
C = * PC;
If (C = 'X') STK. Push (xval );
Else if (C> = '0') & (c <= '9') | (C = '. ') {Szt + = C; PC ++; continue ;}
Else
{
If (! Szt. isempty () {STK. Push (atof (Szt); Szt = "";}
If (! STK. Pop (V2) return false;
If (! STK. Pop (V1) return false;
If (C = '+') STK. Push (V1 + V2 );
Else if (C = '-') STK. Push (V1-V2 );
Else if (C = '*') STK. Push (V1 * V2 );
Else if (C = '/') STK. Push (V1/V2 );
Else return false; // The operator is invalid.
}
PC ++;
}
If (! Szt. isempty () {STK. Push (atof (Szt); Szt = "";}
If (STK. getsize ()! = 1) return false;
Return STK. Pop (* presult );
}
After calbehindparse () is slightly modified, the function for checking the correctness of the post expression can be obtained,As follows:
Bool checkbehindparse (lpctstr lpszparse) // check the post expression
{
Char C;
Const char * Pc = lpszparse;
Double V1, V2;
Carraystacktemp <double, 256> STK;
Cstring Szt = "";
While (* PC! = NULL)
{
C = * PC;
If (C = 'X') STK. Push (1 );
Else if (C> = '0') & (c <= '9') | (C = '. ') {Szt + = C; PC ++; continue ;}
Else
{
If (! Szt. isempty () {STK. Push (atof (Szt); Szt = "";}
If (! STK. Pop (V2) return false;
If (! STK. Pop (V1) return false;
If (C = '+') | (C = '-') | (C = '*') | (C = '/') STK. push (1 );
Else return false; // The operator is invalid.
}
PC ++;
}
If (STK. getsize ()! = 1) return false;
Return true;
}
Based on these functions, you can obtain the direct calculation and check functions of the intermediate expression.:
Bool checkparse (lpctstr lpszparse) // check whether the intermediate expression is correct
{
Cstring SZB;
If (0! = G_mid2behind (lpszparse, SZB ))
Return false;
If (SZB. isempty () return true;
Return checkbehindparse (SZB );
}
Bool calparse (lpctstr lpszparse, double dblvar, double * presult) // calculates the intermediate expression
{
Cstring SZB;
If (0! = G_mid2behind (lpszparse, SZB ))
Return false;
If (SZB. isempty () {* presult = 0; return true ;}
Return calbehindparse (SZB, dblvar, presult );
}
You can use the following test example to test the above function.:
Double dblresult;
Bool Bret = calparse ("X/2 * (x + 2.5)", 2, & dblresult); // calculates the intermediate expression
Note: the code in this article is verified in Windows XP, VC ++ 6 + vcsp5 environment.
Bytes -----------------------------------------------------------------------------------------------
Classic Algorithm for expression evaluation
The classic method used to evaluate an arithmetic expression in code was described by Donald knuth on July 6, 1962 (see references ). Knuth outlines this as three steps:
- Perform syntax analysis on the infix expression
- Converting an infix expression to a suffix expression
- Evaluate the suffix expression
Note that the classic algorithm we mentioned is somewhat simplified: an arithmetic expression contains only the operands, binary operators, and a bracket. In addition, each operand and operator is represented by only one character, making the syntax analysis intuitive.
Expression notation
The most common forms of expression in arithmetic expressions are:Infix and prefixAndSuffixRepresentation. Infix notation is a common method for writing expressions, while prefix and suffix notation are mainly used in computer science.
Infix notation
The infix notation is the regular expression of an arithmetic expression. It is calledInfixThe representation is because each operator is located in the middle of its operand, this notation is only applicable when the operator exactly corresponds to two operands (when the operator is a binary operator, such as addition, subtraction, multiplication, division, and modulo ). When performing syntax analysis on Expressions written in infix notation, you must use parentheses and priority rules to exclude ambiguity.
Syntax: operand1 operator operand2 Example: (A+B)*C-D/(E+F)
|
Prefix notation
In the prefix representation, operators are written before the operands. This representation is often used in computer science, especially in compiler design. To commemorate its inventor Jan Lukasiewicz (see references), this notation is also calledPolish notation.
Syntax : operator operand1 operand2 Example : -*+ABC/D+EF
|
Suffix notation
In the suffix representation, the operator is behind the operand. Suffix notation is also calledReverse Polish notation(Reverse Polish notation, RPN) is widely used because it makes it easy to evaluate expressions.
Syntax : operand1 operand2 operator Example : AB+C*DEF+/-
|
Prefix and suffix notation have three common features:
- The order of the operands is the same as that of the operands in the equivalent infix expression.
- No parentheses
- Irrelevant operator priority
Converting an infix expression to a suffix expression
To convert an expression from an infix expression to an equivalent expression expressed in a suffix notation, you must understand the priority and associativity of operators.PriorityOr the intensity of operators determines the order of values. Operators with higher priorities are evaluated first than operators with lower priorities. If all operators have the same priority, the order of evaluation depends on theirAssociativity. The concatenation of operators defines the order (from right to left or from left to right) of operators of the same priority ).
Left associativity : A+B+C = (A+B)+C Right associativity : A^B^C = A^(B^C)
|
The conversion process includes using the following algorithm to read the operands, operators, and parentheses of the infix expression:
- Initialize an empty stack and leave the result string variable empty.
- Read the infix expression from left to right, one character at a time.
- If the character is an operand, add it to the result string.
- If the character is an operator, the pop operator pops up until it meets opening parenthesis, a lower-priority operator, or a right-bound symbol with the same priority. Press this operator into the (push) stack.
- If the character is an open bracket, press it into the stack.
- If the character is a closed parenthesis (closing parenthesis), all operators will pop up before it is met, and then add them to the result string.
- If the end of the input string is reached, all operators are displayed and added to the result string.
Suffix expression evaluate
Evaluate a suffix expression is simpler than simply evaluate an infix expression. In a suffix expression, parentheses are not required, and the operator priority is no longer effective. You can use the following algorithm to evaluate the suffix expression:
- Initialize an empty Stack
- Read suffix expressions from left to right
- If the character is an operand, press it into the stack.
- If the character is an operator, two operands are displayed, perform the appropriate operation, and then press the result into the stack. If you cannot bring up two operands, the syntax of the suffix expression is incorrect.
- To the end of the suffix expression, the result is displayed from the stack. If the suffix expression format is correct, the stack should be empty.