Expression evaluation

Keywords: C++ calculator less PHP

1: Preface

The so-called expression evaluation is to write a micro-calculator. For example, input: (1+9)* 2/2-1, output 9. For such problems, we usually use stack to simulate mathematical operations. In order to simplify the problem, before proceeding with the following analysis, let's make a convention here: this paper only discusses the four basic operations of +-*/(), and does not do exception handling for unexpected symbols (such as ^) and non-conforming mathematical expressions (such as 2*-1).

II: Thought and Analysis

_We use an array of characters (char s[1000]) to store mathematical expressions, and define a global variable g_pos to represent the subscripts of s [, starting from 0. Firstly, we define two stacks, optr and opnd, which store operators and operands respectively, and put operands directly into opnd when we encounter them.
(1) encounters a negative sign;
(2) encounter right parentheses;
(3) encounter left parentheses;
(4) encounter +-*/;
The first three situations are easy to understand, so let's talk about the fourth. We all know that the four operations are multiplied, divided and subtracted (for example, 2*3+1), so for each operator, we should compare the top symbol level of optr. If the symbol level is higher than the top symbol level of OPTR stack, do nothing and put it on the stack directly. If it is less than or equal, we need to extract the top two numbers of opnd stack and calculate them. There is a problem here. When we encounter the first operator, the OPTR is empty, and we need to compare the level with the top operator of the OPTR stack. What should we do then? To solve this problem, when we initialize optr, we put in a # and set it to the lowest level.
Seen here, you may still have a question, how to determine the sign - minus sign or minus sign? For example - 1 + 2 and 5 - 1 + 2.
_Analysis shows that there are only two cases of negative sign:
The left side of(1) is the left bracket, for example (-1+5*3);
The first character of the(2) string, such as -5*6-1.
In order to facilitate code writing, if there is a negative sign, add a number 0 to the arithmetic stack (which is why the bool value is_minus appears in the following code), that is, convert the expression, such as -1+2 to 0-1+2.

Three: Code

/**
 * 
 * author Limer
 * data   2017-02-24
 * mode   C++ 
 */
#include<iostream>  
#include<algorithm>   
#include<cstring>  
#include<stack>  
#include<cmath>  
using namespace std;

char s[1000];
int  g_pos;//Subscription of character array  

/* Character to Number */
double Translation(int & pos)
{
    double integer = 0.0;    //Integral part  
    double remainder = 0.0;  //Remainder part  
    int c = 0;
    while (s[pos] >= '0'&&s[pos] <= '9')
    {
        integer *= pow(10, c);
        c++;
        integer += (s[pos] - '0');
        pos++;
    }
    if (s[pos] == '.')
    {
        pos++;
        c = 1;
        while (s[pos] >= '0'&&s[pos] <= '9')
        {
            double t = s[pos] - '0';
            t *= pow(0.1, c);
            c++;
            remainder += t;
            pos++;
        }
    }

    return integer + remainder;
}

/* Return operator level */
int GetLevel(char ch)
{
    switch (ch)
    {
    case '+':
    case '-':return 1;
    case '*':
    case '/':return 2;
    case '(':return 0;
    case '#':return -1;
    };
}

/* Operate on two numbers */
double Operate(double a1, char op, double a2)
{
    switch (op)
    {
    case '+':return a1 + a2;
    case '-':return a1 - a2;
    case '*':return a1*a2;
    case '/':return a1 / a2;
    };
}

/* Using two stacks to simulate computation */
double Compute()
{
    stack<char> optr;    //Operator stack  
    stack<double> opnd;  //Operand stack  

    optr.push('#');
    int len = strlen(s);
    bool is_minus = true;  //Judging whether'-'is a minus sign or a minus sign  
    for (g_pos = 0; g_pos < len;)
    {
        //1. minus sign  
        if (s[g_pos] == '-'&&is_minus)  //Minus sign  
        {
            opnd.push(0);
            optr.push('-');
            g_pos++;
        }
        //2. Right parentheses)  
        else if (s[g_pos] == ')')
        {
            is_minus = false;
            g_pos++;
            while (optr.top() != '(')
            {
                double a2 = opnd.top();
                opnd.pop();
                double a1 = opnd.top();
                opnd.pop();
                char op = optr.top();
                optr.pop();

                double result = Operate(a1, op, a2);
                opnd.push(result);
            }

            optr.pop();  //Delete ''  
        }
        //3. figures  
        else if (s[g_pos] >= '0' && s[g_pos] <= '9')
        {
            is_minus = false;
            opnd.push(Translation(g_pos));
        }
        //4. (Left parentheses)  
        else if (s[g_pos] == '(')
        {
            is_minus = true;
            optr.push(s[g_pos]);
            g_pos++;
        }
        //5. + - * / Four  
        else
        {
            while (GetLevel(s[g_pos]) <= GetLevel(optr.top()))
            {
                double a2 = opnd.top();
                opnd.pop();
                double a1 = opnd.top();
                opnd.pop();
                char op = optr.top();
                optr.pop();

                double result = Operate(a1, op, a2);
                opnd.push(result);
            }
            optr.push(s[g_pos]);
            g_pos++;
        }
    }

    while (optr.top() != '#')
    {
        double a2 = opnd.top();
        opnd.pop();
        double a1 = opnd.top();
        opnd.pop();
        char op = optr.top();
        optr.pop();

        double result = Operate(a1, op, a2);
        opnd.push(result);
    }

    return opnd.top();
}

int main()
{
    
    return 0;
}


Turn to my personal blog: http://www.61mon.com/index.php/archives/180/

Posted by four4swords on Sat, 06 Apr 2019 11:57:31 -0700