用Java实现的后序表达式计算类,支持科学计算

用Java实现支持科学计算的数学公式运算类

通过对现有的后序表达式计算方法,经过稍许改动实现支持科学计算

废话不多说,直接上代码

计算类代码如下:

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class ExpressionEvaluationClass {

    // 此方法用于将算术表达式解析成包含操作数和操作符的链表
    public static List<String> Parser(String expression) {
        List<String> list = new ArrayList<String>();// 用于存储表达式的链表
        expression = PiChange(expression);//处理π
        expression = EChange(expression);//处理e

        //判断负数,并将-号转换为负数符号
        if (expression.charAt(0) == '-') {
            StringBuilder sb = new StringBuilder(expression);
            sb.setCharAt(0, 'f');
            expression = sb.toString();
        }
        String newExperssion = expression.replace("(-", "(f");
        //将符号值转化为计算代号
        newExperssion = newExperssion.replace("lg", "G");
        newExperssion = newExperssion.replace("log", "g");
        newExperssion = newExperssion.replace("ln", "L");
        newExperssion = newExperssion.replace("sin", "S");
        newExperssion = newExperssion.replace("cos", "C");
        newExperssion = newExperssion.replace("tan", "T");
        newExperssion = newExperssion.replace("arcSin", "i");
        newExperssion = newExperssion.replace("arcCos", "c");
        newExperssion = newExperssion.replace("arcTan", "t");
        newExperssion = newExperssion.replace("cot", "o");
        newExperssion = newExperssion.replace("sec", "e");
        newExperssion = newExperssion.replace("csc", "s");
        newExperssion = newExperssion.replace("!", "!1");
        newExperssion = newExperssion.replace("°", "°1");
        //取出表达式中的空格符号
        newExperssion = newExperssion.replace("\u00A0", "");
        newExperssion = newExperssion.replaceAll("\\u00A0+", "");

        String str = "";
        for (int i = 0; i < newExperssion.length(); i++) {
            char c = newExperssion.charAt(i);

            if (Character.isDigit(c) || c == '.') {
                str += c;
            } else {
                if (str.length() > 0) {// 此判断是因为有+(这种符号相连的情况
                    //System.out.println(str);
                    list.add(str);
                    str = "";
                }
                //System.out.println(c);
                list.add(String.valueOf(c));
            }
        }

        if (str.length() > 0) {// 此判断是因为可能表达式不是以=结尾
            //System.out.println(str);
            list.add(str);
            str = "";
        }
        return list;
    }

    // 此类用于将中序表达式转译成后序表达式
    public static List<String> Trans(List<String> list) {
        Stack<String> stack;// 用于存储操作符的栈
        List<String> postfixList;// 用于存储后序表达式的链表
        stack = new Stack<String>();
        postfixList = new ArrayList<String>();

        for (String str : list) {
            // 这个分支是当前项是操作符号的情况
            if (str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/") || str.equals("%") || str.equals("(") || str.equals(")") ||
                    str.equals("g") || str.equals("L") || str.equals("G") || str.equals("S") || str.equals("C") || str.equals("T") || str.equals("i") ||
                    str.equals("c") || str.equals("t") || str.equals("o") || str.equals("e") || str.equals("s") || str.equals("!") || str.equals("f")
                    || str.equals("√") || str.equals("°") || str.equals("^")) {
                String opThis = str;
                if (stack.size() == 0) {
                    // 如果栈为空,直接把操作符推入栈
                    stack.push(opThis);
                } else if (str.equals("(")) {
                    // 如果操作符是左括号,直接推入栈
                    stack.push(opThis);
                } else if (str.equals(")")) {
                    // 如果操作符是右括号,则往前找左括号,将左括号之后的操作符放到后续表达式列表中

                    while (stack.peek().equals("(") == false) { // stack.peek()是取栈顶元素而不弹出
                        postfixList.add(stack.pop());
                    }
                    stack.pop();// 左括号丢弃,由此完成了去括号的过程
                } else {
                    // 看栈顶元素,如果它优先级大于等于当前操作符的优先级,则弹出放到后续表达式列表中
                    while (stack.size() > 0 && (getOpLevel(stack.peek()) >= getOpLevel(opThis))) {
                        postfixList.add(stack.pop());
                    }
                    stack.push(opThis);// 当前操作符入栈
                }
            } else {
                // 这个分支是当前项是操作数的情况
                postfixList.add(str);// 操作数直接入栈
            }
        }
        // 将栈中余下的操作符弹出放到后续表达式列表中
        while (stack.size() > 0) {
            String opTop = stack.pop();
            postfixList.add(opTop);
        }
        return postfixList;
    }

    // 取得操作符的等级
    static int getOpLevel(String op) {
        if (op.equals("+") || op.equals("-")) {
            return 0;
        } else if (op.equals("*") || op.equals("/") || op.equals("%")) {
            return 1;
        } else if (op.equals("g") || op.equals("L") || op.equals("G") || op.equals("S") || op.equals("C") || op.equals("T") || op.equals("i") ||
                op.equals("c") || op.equals("t") || op.equals("o") || op.equals("e") || op.equals("s") || op.equals("!")) {
            return 2;
        } else if (op.equals("√") || op.equals("°") || op.equals("^")) {
            return 3;
        }else if(op.equals("f")) {
            return 4;
        }
        return -1;
    }

    // 此方法用于计算后续表达式的值    调用顺序4
    public static String Calculator(List<String> list) {
        Stack<String> stack = new Stack<String>();
        for (String str : list) {//遍历
            // 这个分支是当前项是操作符号的情况
            if (str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/") || str.equals("%") || str.equals("(") || str.equals(")") ||
                    str.equals("g") || str.equals("L") || str.equals("G") || str.equals("S") || str.equals("C") || str.equals("T") || str.equals("i") ||
                    str.equals("c") || str.equals("t") || str.equals("o") || str.equals("e") || str.equals("s") || str.equals("!") || str.equals("f")
                    || str.equals("√") || str.equals("°") || str.equals("^")) {
                double result = 0;
                if (str.equals("+")) {
                    double op2 = Double.valueOf(stack.pop());
                    double op1 = Double.valueOf(stack.pop());
                    result = op1 + op2;
                } else if (str.equals("-")) {
                    double op2 = Double.valueOf(stack.pop());
                    double op1 = Double.valueOf(stack.pop());
                    result = op1 - op2;
                } else if (str.equals("*")) {
                    double op2 = Double.valueOf(stack.pop());
                    double op1 = Double.valueOf(stack.pop());
                    result = op1 * op2;
                } else if (str.equals("/")) {
                    double op2 = Double.valueOf(stack.pop());
                    double op1 = Double.valueOf(stack.pop());
                    result = op1 / op2;
                } else if (str.equals("%")) {
                    double op2 = Double.valueOf(stack.pop());
                    double op1 = Double.valueOf(stack.pop());
                    result = op1 % op2;
                } else if (str.equals("f")) {//负数符号
                    double op = Double.valueOf(stack.pop());
                    result = -1 * op;
                } else if (str.equals("g")) {//log
                    double op2 = Double.valueOf(stack.pop());
                    double op1 = Double.valueOf(stack.pop());
                    if (op1 <= 0) {
                        return "对数log的操作数须大于零";
                    }
                    if (op2 <= 0) {
                        return "对数log的操作数须大于零";
                    }
                    result = Math.log(op2) / Math.log(op1);
                } else if (str.equals("L")) {//ln
                    double op = Double.valueOf(stack.pop());
                    if (op <= 0) {
                        return "对数ln的操作数须大于零";
                    }
                    result = Math.log(op);
                } else if (str.equals("G")) {//lg
                    double op = Double.valueOf(stack.pop());
                    if (op <= 0) {
                        return "对数lg的操作数须大于零";
                    }
                    result = Math.log10(op);
                } else if (str.equals("S")) {//sin
                    double op = Double.valueOf(stack.pop());
                    result = Math.sin(op);
                } else if (str.equals("C")) {//cos
                    double op = Double.valueOf(stack.pop());
                    result = Math.cos(op);
                } else if (str.equals("T")) {//tan
                    double op = Double.valueOf(stack.pop());
                    if (Math.abs(op % Math.PI * 2) == 1) {
                        return "tan取值有错误";
                    }
                    result = Math.tan(op);
                } else if (str.equals("i")) {//arcsin
                    double op = Double.valueOf(stack.pop());
                    if (op > 1 || op < (-1)) {
                        return "arcSin的取值有错误";
                    } else {
                        result = Math.asin(op);
                    }
                } else if (str.equals("c")) {//arccos
                    double op = Double.valueOf(stack.pop());
                    if (op > 1 || op < (-1)) {
                        return "arcCos的取值有错误";
                    } else {
                        result = Math.acos(op);
                    }
                } else if (str.equals("t")) {//arctan
                    double op = Double.valueOf(stack.pop());
                    result = Math.atan(op);
                } else if (str.equals("o")) {//cot
                    double op = Double.valueOf(stack.pop());
                    //角度
                    double so = Math.sin(op);
                    double co = Math.cos(op);
                    result = co / so;
                } else if (str.equals("e")) {//sec
                    double op = Double.valueOf(stack.pop());
                    double ec = Math.cos(op);
                    if (ec == 0) {
                        return "sec取值有错误";
                    } else {
                        result = 1 / ec;
                    }
                } else if (str.equals("s")) {//csc
                    double op = Double.valueOf(stack.pop());
                    double ss = Math.sin(op);
                    if (ss == 0) {
                        return "csc取值有错误";
                    } else {
                        result = 1 / ss;
                    }
                } else if (str.equals("!")) {//阶乘
                    stack.pop();
                    double op1 = Double.valueOf(stack.pop());
                    if (op1 < 0) {
                        return "阶乘数有误";
                    }
                    result = getN(op1);
                } else if (str.equals("√")) {//开方
                    double op2 = Double.valueOf(stack.pop());
                    double op1 = Double.valueOf(stack.pop());
                    //负值不能开偶次方
                    if ((op2 < 0 && op1 % 2 == 0 || op1 == 0)) {
                        return "负数不能开偶次方!";
                    }
                    if (op2 < 0) {
                        result = -Math.pow(-op2, 1 / op1);
                    } else {
                        result = Math.pow(op2, 1 / op1);
                    }
                } else if (str.equals("°")) {//角度制转弧度制
                    stack.pop();
                    double op1 = Double.valueOf(stack.pop());
                    result = (op1) * Math.PI / 180;
                } else if (str.equals("^")) {//幂
                    double op2 = Double.valueOf(stack.pop());
                    double op1 = Double.valueOf(stack.pop());
                    if (op2 > 0 && op2 < 1) {//幂次数大于零小于1,是开方操作
                        if (op1 < 0 && ((1 / op2) % 2 == 0)) {
                            return "负数不能开偶次方!";
                        }
                        if (op1 < 0) {
                            result = -Math.pow(-op1, op2);
                        }
                    } else {
                        result = Math.pow(op1, op2);
                    }
                }

                stack.push((new DecimalFormat("0.#####").format(result)));
            } else {
                // 如果是操作数先直接入栈
                stack.push(str);
            }
        }
        // 取得结果
        return stack.peek();
    }

    private static double getN(double n) {//计算阶乘的方法
        if (n == 0)
            return 1;
        double sum = 1.0;
        for (int s = 1; s <= n; s++) {
            sum *= s;
        }
        return sum;
    }

    private static String PiChange(String ss) {//π转换
        String aa2 = ss;
        int ssLast = ss.lastIndexOf('π');
        if (ssLast >= 0) {
            if (ssLast != 0 && ss.charAt(ssLast - 1) >= '0' && ss.charAt(ssLast - 1) <= '9') {//π不在首位并且前面一位是数字
                StringBuilder sb = new StringBuilder(ss);
                sb.setCharAt(ssLast, '*');//将π替换为*
                sb.insert(ssLast + 1, Math.PI);//在*后面加上*Math.PI
                aa2 = sb.toString();//转为字符串格式
            } else {
                StringBuilder sb = new StringBuilder(ss);
                sb.setCharAt(ssLast, '\u00A0');
                sb.insert(ssLast + 1, Math.PI + "");
                aa2 = sb.toString();
                aa2 = aa2.replace("\u00A0", "");
            }
            System.out.println(aa2);
            while (aa2.lastIndexOf('π') >= 0) {
                aa2 = PiChange(aa2);
            }
        }
        return aa2;
    }

    private static String EChange(String ss) {//е转换
        String aa2 = ss;
        int ssLast = ss.lastIndexOf('е');
        if (ssLast > 0) {
            if (ssLast != 0 && ss.charAt(ssLast - 1) >= '0' && ss.charAt(ssLast - 1) <= '9') {//е不在首位并且前面一位是数字
                StringBuilder sb = new StringBuilder(ss);
                sb.setCharAt(ssLast, '*');//将е替换为*
                sb.insert(ssLast + 1, Math.E);//在*后面加上*Math.E
                aa2 = sb.toString();//转为字符串格式
            } else {
                StringBuilder sb = new StringBuilder(ss);
                sb.setCharAt(ssLast, '\u00A0');
                sb.insert(ssLast + 1, Math.E + "");
                aa2 = sb.toString();
                aa2 = aa2.replace("\u00A0", "");
            }
            while (aa2.lastIndexOf('е') >= 0) {
                aa2 = EChange(aa2);
            }
        }
        return aa2;
    }
}

怎么使用:

try {
	List<String> list = ExpressionEvaluationClass.Parser("-2.5+sin(π/2)/9!+2log8+lg10+(-3)√(-9)");//将算术表达式解析成包含操作数和操作符的链表
	<String> list2 = ExpressionEvaluationClass.Trans(list);//构建后序表达式
	System.out.println("计算结果为:"+ExpressionEvaluationClass.Calculator(list2));//计算后序表达式
	} catch (Exception e) {
		e.printStackTrace();
		System.out.println("请检查表达式是否正确");
	}

值得注意:
运算符优先级如下:
加、减优先级为0
乘、除、%优先级为1
对数、三角函数、阶乘符号优先级为2
开方、幂运算、度优先级为3
负号优先级为4

负数只支持表达式首位添加负号如:-5+6 ,和在括号内加负号:sin(-5)

三角函数中反三角函数写法为arcSin,三角函数可不加括号,但需要考虑运算符号的优先级,三角函数前不允许直接添加数字正确写法:2*sinπ

开方负号√为双目运算符,第一位为开N次方,第二位为被开方数:2√4

log也是双目运算符,第一位为底数,第二位为真数:2log8

lg、ln为单目运算符:lg10;

表达式中的多数方法在进行计算时,会转换为计算代号:

//将符号值转化为计算代号
        newExperssion = newExperssion.replace("lg", "G");
        newExperssion = newExperssion.replace("log", "g");
        newExperssion = newExperssion.replace("ln", "L");
        newExperssion = newExperssion.replace("sin", "S");
        newExperssion = newExperssion.replace("cos", "C");
        newExperssion = newExperssion.replace("tan", "T");
        newExperssion = newExperssion.replace("arcSin", "i");
        newExperssion = newExperssion.replace("arcCos", "c");
        newExperssion = newExperssion.replace("arcTan", "t");
        newExperssion = newExperssion.replace("cot", "o");
        newExperssion = newExperssion.replace("sec", "e");
        newExperssion = newExperssion.replace("csc", "s");
        newExperssion = newExperssion.replace("!", "!1");
        newExperssion = newExperssion.replace("°", "°1");

本人利用Android studio编写了一个计算器小程序,一来可以更方便的输入表达式计算,二来可以通过按键限制输入的字符,减少表达式出现错误的可能。

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值