表达式求值(带括号和小数点)java和c++

最近准备在android上写一个计算器,发现根本不会写呀,于是就在网上找怎么求表达式的值,最后找到了一个后缀表达式转中缀表达式再计算的方法,也没看懂,正好在学数据结构的栈,发现里面正好有逆波兰表达法,于是就用java写了一个表达式计算。然后又改了个c++版.
首先是准备工作,在计算表达式之前,我们需要知道到底用什么方法才能计算,对于一个算术表达式(中缀表达式),我们需要先转换为逆波兰(后最表达式)后,才能进行计算,不知道的要自行学习了,不然就像我一样找到了代码却看不懂。
首先对于表达式如 “9.2+(3-1.1)*3+10/2” 我用String 保存起来,要想对它进行转化,首先要判断它到底是不是标准的表达式,于是就有:

/**
     * 是否为算术表达式
     * 
     * @param str
     * @return
     */
    private static boolean isExpression(String str) {
        int flag = 0;
        for (int i = 0; i < str.length() - 1; i++) {
            char ch = str.charAt(i);
            char chb = str.charAt(i + 1);
            if ((!isNum(ch) && i == 0) && ch != '(' || !isNum(chb)
                    && (i == str.length() - 2) && chb != ')') {
                System.out.println("首尾不是数字---->" + ch + chb);
                return false;
            }
            if ((ch == '.' && !isNum(chb)) || (!isNum(ch) && chb == '.')) {
                System.out.println("小数点前后不是数字--->" + ch + chb);
                return false;
            }
            if (isOperator(ch) && !isNum(chb) && chb != '(') {
                System.out.println("运算符不是数字--->" + ch + chb);
                return false;
            }
            if (isNum(ch) && !isOperator(chb) && chb != '.' && chb != ')'
                    && !isNum(chb)) {
                System.out.println("数字后不是运算符--->" + ch + chb);
                return false;
            }
            if (ch == '(') {
                flag++;
            }
            if (chb == ')') {
                flag--;
            }
        }
        if (flag != 0) {
            System.out.println("括号不匹配--->");
            return false;
        }
        return true;
    }

对于标准的表达式就好办些了,但是还是没什么变化,想要把一个字符串算术表达式转化为后缀表达式,我需要先把它分解成数字和运算符,每个数字和运算符都放入String然后装入List里,了代码如下:

/**
     * 分解表达式
     * 
     * @param str
     * @return
     */
    private static List<String> resolveString(String str) {
        List<String> list = new ArrayList<String>();
        String temp = "";
        for (int i = 0; i < str.length(); i++) {
            final char ch = str.charAt(i);
            if (isNum(ch) || ch == '.') {
                char c = str.charAt(i);
                temp += c;
            } else if (isOperator(ch) || ch == ')') {
                if (!temp.equals("")) {
                    list.add(temp);
                }
                list.add("" + ch);
                temp = "";
            } else if (ch == '(') {
                list.add("" + ch);
            }
            if (i == str.length() - 1) {
                list.add(temp);
            }
        }
        return list;
    }

好了,完成了三分之一,接下来就是重点了,就是把中缀表达式转化为后缀表达式,转换规则是:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分,若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低 与栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。当然,我们这里是要后缀表达式的,所以就把输出的内容放到List里了。直接代码

/**
     * 中缀表达式转换后缀
     * 
     * @param list
     * @return
     */
    private static List<String> nifix_to_post(List<String> list) {
        Stack<String> stack = new Stack<String>();
        List<String> plist = new ArrayList<String>();
        for (String str : list) {
            if (isDouble(str)) {
                plist.add(str);
            }
            if (isStrOperator(str) && stack.isEmpty()) {
                stack.push(str);
            } else if (isStrOperator(str) && !stack.isEmpty()) {
                String last = stack.lastElement();
                if (heightOperator(str, last) || str.equals("(")) {
                    stack.push(str);
                } else if (!heightOperator(str, last) && !str.equals(")")) {
                    while (!stack.isEmpty() && !stack.lastElement().equals("(")) {
                        plist.add(stack.pop());
                    }
                    stack.push(str);
                } else if (str.equals(")")) {
                    while (!stack.isEmpty()) {
                        String pop = stack.pop();
                        if (!pop.equals("(")) {
                            plist.add(pop);
                        }
                        if (pop.equals("(")) {
                            break;
                        }
                    }
                }
            }
//          for(String o : stack){
//              System.out.println(o);
//          }
        }
        while (!stack.isEmpty()) {
            plist.add(stack.pop());
        }
//      for (String pl : plist) {
//          System.out.println(pl);
//      }
        return plist;
    }

其中有一些自己写的工具方法如下:

/**
     * 字符是否为数字
     * 
     * @param ch
     * @return
     */
    private static boolean isNum(char ch) {
        if (ch <= '9' && ch >= '0') {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 字符串是否为Double类型
     * 
     * @param s
     * @return
     */
    private static boolean isDouble(String s) {
        try {
            Double.valueOf(s);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 字符是否为运输符
     * 
     * @param ch
     * @return
     */
    private static boolean isOperator(char ch) {
        if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=') {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 字符串是否为运算符
     * 
     * @param s
     * @return
     */
    private static boolean isStrOperator(String s) {
        if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")
                || s.equals("(") || s.equals(")")) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 比较运算符优先级
     * 
     * @param o1
     * @param o2
     * @return
     */
    private static boolean heightOperator(String o1, String o2) {
        if ((o1.equals("*") || o1.equals("/"))
                && (o2.equals("+") || o2.equals("-")) || o2.equals("(")) {
            return true;
        } else if ((o1.equals("+") || o1.equals("-"))
                && (o2.equals("*") || o2.equals("/"))) {
            return false;
        } else if ((o1.equals("*") || o1.equals("/"))
                && ((o2.equals("*") || o2.equals("/")))) {
            return true;
        } else if ((o1.equals("+") || o1.equals("-"))
                && (o2.equals("+") || o2.equals("-"))) {
            return true;
        } else {
            return false;
        }
    }

好了,转换完成,终于转换成后缀表达式了,可以计算了,对于后缀表达式的计算,虽然说也用到了栈,但比转换可简单多了,它的规则是:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是运算符,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。来了:

/**
     * 计算后缀表达式
     * 
     * @param list
     * @return
     */
    private static double get_postfis_result(List<String> list) {
        Stack<String> stack = new Stack<String>();
        for (String str : list) {
            if (isDouble(str)) {
                stack.push(str);
            } else if (isStrOperator(str)) {
                double n2 = Double.valueOf(stack.pop());
                double n1 = Double.valueOf(stack.pop());
                stack.push("" + getCountResult(str, n1, n2));
            }
        }
        return Double.valueOf(stack.pop());
    }

最后用主函数测试

public static void main(String[] args) {
        String str = "9.2+(3-1.1)*3+10/2";
        if (!isExpression(str)) {
            System.out.println("ERROR!!");
            return;
        }
        List<String> list = resolveString(str);
        list = nifix_to_post(list);
        System.out.println(str + "=" + get_postfis_result(list));
    }

最后结果是19.9。 对于我这么菜,只能写这么个简单的了,最后我还改了一个c++版的,和这个基本没啥大的差别,下面有源码下载,想看的看一下。代码:

#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <stdlib.h>
/*
    Name: ExpressionResult.cpp
    Copyright: null
    Author: runing
    Date: 26-03-15 15:15
    Description: getExpressionResult
*/

using namespace std;

/*
    字符是否为数字
*/
bool isNum(char ch)
{
    if (ch <= '9' && ch >= '0')
    {
        return true;
    } else
    {
        return false;
    }
}

/*
    字符是否为运算符
*/
bool isOperator(char ch)
{
    if (ch == '+' || ch == '-' || ch == '*'
            || ch == '/' || ch == '=')
    {
        return true;
    } else
    {
        return false;
    }
}

/*
    字符是否为算术表达式
*/
bool isExpression(const string & str)
{
    int flag = 0;
    for (int i = 0; i < str.length() - 1; i++)
    {
        const char ch = str[i];
        const char chb = str[i + 1];
        if ((!isNum(ch) && i == 0) && ch != '(' || !isNum(chb)
                && (i == str.length() - 2) && chb != ')')
        {
            cout << "首尾不是数字---->" << ch << chb << endl;
            return false;
        }
        if ((ch == '.' && !isNum(chb)) || (!isNum(ch) && chb == '.'))
        {
            cout << "小数点前后不是数字--->" << ch << chb << endl;
            return false;
        }
        if (isOperator(ch) && !isNum(chb) && chb != '(')
        {
            cout << "运算符不是数字--->" << ch << chb << endl;
            return false;
        }
        if (isNum(ch) && !isOperator(chb) && chb != '.' && chb != ')'
                && !isNum(chb))
        {
            cout << "数字后不是运算符--->" << ch << chb << endl;
            return false;
        }
        if (ch == '(')
        {
            flag++;
        }
        if (chb == ')')
        {
            flag--;
        }
    }
    if (flag != 0)
    {
        cout << "括号不匹配--->" << endl;
        return false;
    }
    return true;
}

/*
    字符串转换浮点型
*/
double transformString(const string &str)
{
    char char_Str[30];
    int i = 0;
    for (i = 0; i < str.length(); i++)
    {
        char_Str[i] = str[i];
    }
    char_Str[i] = '\0';
    return atof(char_Str);
}

/*
    浮点型转换字符串
*/
string transformDouble(const double &d1)
{
    char char_str[30];
    gcvt(d1, 8, char_str);
    string str = "";
    int i = 0;
    for (i = 0; char_str[i] != '\0'; i++)
    {
        str.append(1, char_str[i]);
    }
    return str;
}

/*
    分解算术表达式字符串
*/
vector<string> & resolveString(vector<string> & s_vector, const string & str)
{
    string temp = "";
    for (int i = 0; i < str.length(); i++)
    {
        const char ch = str[i];
        if (isNum(ch) || ch == '.')
        {
            temp += ch;
        } else if (isOperator(ch) || ch == ')')
        {
            if (temp != "")
            {
                s_vector.push_back(temp);
                temp = "";
            }
            temp.append(1, ch);
            s_vector.push_back(temp);
            temp = "";
        } else if (ch == '(')
        {
            temp.append(1, ch);
            s_vector.push_back(temp);
            temp = "";
        }
        if (i == str.length() - 1)
        {
            s_vector.push_back(temp);
        }
    }
    return  s_vector;
}

/*
    字符串是否为数字
*/
bool isDouble(const string &str)
{
    if (str == "")
    {
        return false;
    }
    if (str[0] == '.' || str[str.length() - 1] == '.')
    {
        return false;
    }
    if (str.length() > 1)
    {
        if (str[0] == '0' && str[1] != '.')
        {
            return false;
        }
    }
    for (int i = 0; i < str.length(); i++) {
        if (!isNum(str[i]) && str[i] != '.')
        {
            return false;
        }
    }
    return true;
}

/*
    字符串是否为运算符
*/
bool isStrOperator(const string & str)
{
    if (str == "+" || str == "-" || str == "*" || str == "/"
            || str == "(" || str == ")") {
        return true;
    } else
    {
        return false;
    }
}

/*
    比较运算符优先级
*/
bool heightOperator(const string &o1, const string &o2)
{
    if ((o1 == "*" || o1 == "/")
            && (o2 == "+" || o2 == "-") || o2 == "(")
    {
        return true;
    } else if ((o1 == "+" || o1 == "-")
               && (o2 == "*" || o2 == "/"))
    {
        return false;
    } else if ((o1 == "*" || o1 == "/")
               && ((o2 == "*" || o2 == "/")))
    {
        return true;
    } else if ((o1 == "+" || o1 == "-")
               && (o2 == "+" || o2 == "-"))
    {
        return true;
    } else
    {
        return false;
    }
}

/*
    中缀表达式转后缀
*/
vector<string> & nifix_to_post(vector<string> & s_vector
                               , vector<string> & post_v)
{
    stack<string> s_stack;
    for (int i = 0; i < s_vector.size(); i++)
    {
        const string str = s_vector[i];
        if (isDouble(str))
        {
            post_v.push_back(str);
        } if (isStrOperator(str) && s_stack.empty())
        {
            s_stack.push(str);
        } else if (isStrOperator(str) && !s_stack.empty())
        {
            string last = s_stack.top();
            if (heightOperator(str, last) || str == "(")
            {
                s_stack.push(str);
            } else if (!heightOperator(str, last) && str != ")")
            {
                while (!s_stack.empty())
                {
                    string pop = s_stack.top();
                    post_v.push_back(pop);
                    s_stack.pop();
                }
                s_stack.push(str);
            } else if (str == ")")
            {
                while (!s_stack.empty())
                {
                    string pop = s_stack.top();
                    if (pop != "(")
                    {
                        post_v.push_back(pop);
                        s_stack.pop();
                    } else
                    {
                        s_stack.pop();
                    }
                    if (pop == "(")
                    {
                        break;
                    }
                }
            }
        }
    }
    while (!s_stack.empty())
    {
        post_v.push_back(s_stack.top());
        s_stack.pop();
    }
//  for(int i = 0;i < post_v.size();i++){
//      cout<< post_v[i]<< endl;
//  }
}

/*
    两数算术运算
*/
double getCountResult(string oper, double num1, double num2)
{
    if (oper == "+")
    {
        return num1 + num2;
    } else if (oper == "-")
    {
        return num1 - num2;
    } else if (oper == "*")
    {
        return num1 * num2;
    } else if (oper == "/")
    {
        return num1 / num2;
    } else
    {
        return 0;
    }
}

/*
    计算后缀表达式
*/
double get_postfis_rearut(vector<string> & post_v)
{
    stack<string> e_stack;
    string temp = "";
    for (int i = 0; i < post_v.size(); i++)
    {
        string str = post_v[i];
        if (isDouble(str))
        {
            e_stack.push(str);
        } else if (isStrOperator(str))
        {
            double n2 = transformString(e_stack.top());
            e_stack.pop();
            double n1 = transformString(e_stack.top());
            e_stack.pop();
            double sum = getCountResult(str, n1, n2);
            temp += transformDouble(sum);
            e_stack.push(temp);
            temp = "";
        }
    }
    return transformString(e_stack.top());
}

int main()
{
    string str = "4*((5-2)+5*2.4)";//"9+(3-1)*3+10/2";
    vector<string> s_vector;
    vector<string> post_v;
    if (!isExpression(str))
    {
        return 0;
    }
    s_vector = resolveString(s_vector, str);
//  for(int i = 0;i < s_vector.size();i++)
//  {
//      cout<< s_vector[i]<< endl;
//  }
    nifix_to_post(s_vector, post_v);
    cout << str << " = " << get_postfis_rearut(post_v);
    return 0;
}
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用栈实现复杂表达式求值C++代码: ```c++ #include <iostream> #include <stack> #include <string> #include <cstring> #include <cmath> using namespace std; // 优先级比较函数 int cmp(char op1, char op2) { if (op1 == '(' || op2 == '(') { return -1; } if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-')) { return -1; } else { return 1; } } // 计算函数 double calc(double num1, double num2, char op) { switch (op) { case '+': return num1 + num2; case '-': return num1 - num2; case '*': return num1 * num2; case '/': return num1 / num2; case '^': return pow(num1, num2); default: return 0; } } // 将中缀表达式转成后缀表达式 string infixToPostfix(string infix) { stack<char> s; string postfix; for (int i = 0; i < infix.length(); i++) { char c = infix[i]; if (isdigit(c) || c == '.') { // 数字和小数点直接输出 postfix += c; continue; } postfix += ' '; // 操作符之间加空格 while (!s.empty() && cmp(s.top(), c) == 1) { // 栈顶元素优先级大于等于当前操作符 postfix += s.top(); s.pop(); postfix += ' '; } if (c == ')') { // 如果是右括号,弹出直到左括号 while (!s.empty() && s.top() != '(') { postfix += s.top(); s.pop(); postfix += ' '; } s.pop(); } else { // 其他情况直接入栈 s.push(c); } } while (!s.empty()) { postfix += ' '; postfix += s.top(); s.pop(); } return postfix; } // 计算后缀表达式 double calcPostfix(string postfix) { stack<double> s; char buf[100]; for (int i = 0; i < postfix.length(); i++) { char c = postfix[i]; if (isdigit(c) || c == '.') { // 数字直接入栈 int j = i, k = 0; while (isdigit(postfix[j]) || postfix[j] == '.') { buf[k++] = postfix[j++]; } buf[k] = '\0'; double num = atof(buf); s.push(num); i = j - 1; } else if (c != ' ') { // 操作符弹出栈顶元素计算 double num2 = s.top(); s.pop(); double num1 = s.top(); s.pop(); s.push(calc(num1, num2, c)); } } return s.top(); } int main() { string infix; cout << "请输入中缀表达式:"; getline(cin, infix); string postfix = infixToPostfix(infix); cout << "后缀表达式为:" << postfix << endl; double result = calcPostfix(postfix); cout << "计算结果为:" << result << endl; return 0; } ``` 这个代码通过将中缀表达式转换为后缀表达式,然后使用栈计算后缀表达式来实现复杂表达式求值。其中,`cmp`函数用于比较两个操作符的优先级,`calc`函数用于计算两个数和一个操作符的结果,`infixToPostfix`函数用于将中缀表达式转换为后缀表达式,`calcPostfix`函数用于计算后缀表达式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值