Java利用栈根据基本算式计算最终结果(计算器)

目录

前言

一、概念引入

中缀表达式和后缀表达式

二、问题分析

1.利用后缀表达式进行计算

2.中缀表达式转后缀表达式

二、代码实现


前言

给你一个字符串"10-6-(10-((3+40.2)+8))*5+8",你能根据这个字符串中的算式计算出最终的结果吗?有些人说,我根据数字和符号一个一个分析,一个一个new,一个一个加减乘除,当然可以!不过,这样怕是要花费巨长的时间......

所以,我们有好一点的方法来进行计算,实现一个真正能实现的计时器功能吗?当然可以,在这里就利用栈来解决这一类问题。


一、概念引入

栈是一种操作受限的线性表,只允许从一端插入和删除数据,他就像一个木桶,当数据被加进木桶时,数据会被存放到栈的底端,当需要使用数据时,只能从栈顶开始取出数据。简单地说,栈中的数据符合 先入后出,后入先出 的原则。于是我们把数据放入栈中的操作叫做push,从栈中取出数据的操作称为pop,以此来对数据进行操作。

中缀表达式和后缀表达式

在我们日常生活中,最常见的运算表达式如:(3+5)-6+8,10-6-(10-((3+40.2)+8))*5+8这些(小学学过)的表达式,我们就称之为 中缀表达式。中缀表达式的求值是我们最熟悉的,但是这对于计算机来说却犯难了,我们人知道如括号,乘号等具有优先级别的子式会先进行计算,但是计算机要怎么来处理这个问题呢?

于是在前人的研究下,后缀表达式 诞生了,后缀表达式则非常适用于计算机的运算,后缀表达式的运算符主要位于操作数之后,如:

(3+5)-6+8 对应的后缀表达式为:3 5 + 6 - 8 +

10-6-(10-((3+40.2)+8))*5+8 对应的后缀表达式为:10 6 - 10 3 40.2 + 8 + - 5 * - 8 +

这个后缀表达式是什么意思呢?后缀表达式是怎么得出来的呢?后缀表达式到底实现了什么样的功能呢?接下来就对问题一一分析。

二、问题分析

1.利用后缀表达式进行计算

以上方的 (3+5)-6+8 对应的后缀表达式为:3 5 + 6 - 8 + 为例,计算机可以如何利用这个表达式对这个算式进行计算呢?

第一步:从左至右对后缀表达式进行扫描,将扫描出来的数字压入堆栈,这里就将3和5压入堆栈;

第二步,遇到运算符,弹出栈顶元素和次顶元素,这里就是5和3,利用运算符计算值,这里就是3+5(这里一定注意,运算是次顶元素在前,栈顶元素在后,避免减法和除法求反),得到结果8,再将8入栈。

第三步:接下来又扫描到了数字,此时又将该数字压入栈,这里是将6压入栈

第四步:接下来,遇到了运算符,又将栈中的两个数字进行运算,算出的结果放入栈中,如此循环,当运算到最后一个数字时,栈中最后一个数字即为最后的结果。

利用后缀表达式,计算机的运算就变得非常简单了,就可以根据表达式精确地运算等式的值。所以现在的问题就是,如何将中缀表达式转换为后缀表达式呢?

2.中缀表达式转后缀表达式

中缀表达式如何转为后缀表达式呢?具体步骤如下:

第一步:初始化两个栈:运算符利用栈2储存,数字利用栈1进行储存;

第二步:从左至右扫描中缀表达式; 遇到操作数时,将其压至栈1;

第三步:遇到运算符时,对运算符的优先级进行判断:

        1. 如果栈2为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;

        2. 否则,若优先级比栈顶运算符的高,也将运算符压入栈1;

        3. 否则,将栈2顶的运算符弹出并压入到栈1中,再次循环与栈2中新的栈顶运算符相比较;

第四步:遇到括号时,进行判断:

        1. 如果是左括号“(”,则直接压入栈2

        2. 如果是右括号“)”,则依次弹出栈2栈顶的运算符,并压入栈1,直到遇到左括号为止,此时将这一对括号丢弃.

第五步:重复判断,直至表达式的最右边。

最后一步:判断完成之后,将栈2剩余的运算符依次pop出并且压入栈1,完成之后,依次pop出栈1的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式


二、代码实现

中缀表达式转后缀表达式

public static String toReversePolish(String expression) {
        Stack<String> stack1 = new Stack<>();
        Stack<String> stack2 = new Stack<>();

        String number = "";
        for (int i = 0; i < expression.length();) {
            boolean isAll = false;
            while((expression.charAt(i)>='0' && expression.charAt(i) <= '9') || expression.charAt(i)=='.') {
                number += expression.charAt(i);
                i++;
                if (i == expression.length()) {
                    isAll = true;
                    break;
                }
            }
            if (!number.isEmpty()) {
                stack2.push(new StringBuffer(number).reverse().toString());
                number = "";
            }
            if (isAll) {
                break;
            }
            if (expression.charAt(i) == ')') {
                while (!stack1.peek().equals("(")) {
                    stack2.push(stack1.pop());
                }
                stack1.pop();
                i++;
                continue;
            }

            while(!(expression.charAt(i)>='0' && expression.charAt(i) <= '9')) {
                char symbol = expression.charAt(i);
                if ((stack1.size() == 0) || (stack1.peek().equals("(")) || (symbol=='(')) {
                    stack1.push(symbol+"");
                    i++;
                    break;
                }
                if ((symbol == '+') || (symbol == '-')) {
                    stack2.push(stack1.pop());
                    continue;
                } else {
                    if ((stack1.peek().equals("+")) || (stack1.peek().equals("-"))) {
                        stack1.push(symbol+"");
                        i++;
                        break;
                    }
                    if ((stack1.peek().equals("*")) || (stack1.peek().equals("/"))) {
                        stack2.push(stack1.pop());
                        continue;
                    }
                }
            }
        }
        while(stack1.size() != 0) {
            stack2.push(stack1.pop());
        }
        String s1 = "";
        while(stack2.size() != 0) {
            s1 += stack2.pop();
            if (stack2.size() != 0) {
                s1 += " ";
            }
        }
        return new StringBuffer(s1).reverse().toString();
    }

计算功能的实现

public static void main(String[] args) {
        String ReversePolish = toReversePolish("10-6-(10-((3+40.2)+8))*5+8");
        //6 10 3 40.2 + 8 + - 5 * - 8 +
        String[] expression = ReversePolish.split(" ");
        Stack<Double> stack = new Stack<>();
        for (int i = 0; i < expression.length; i++) {
            switch (expression[i]) {
                case "+" : {
                    double num1 = stack.pop();
                    double num2 = stack.pop();
                    double result = num1+num2;
                    stack.push(result);
                    break;
                }
                case "-" : {
                    double num1 = stack.pop();
                    double num2 = stack.pop();
                    double result = num2-num1;
                    stack.push(result);
                    break;
                }
                case "*" : {
                    double num1 = stack.pop();
                    double num2 = stack.pop();
                    double result = num1*num2;
                    stack.push(result);
                    break;
                }
                case "/" : {
                    double num1 = stack.pop();
                    double num2 = stack.pop();
                    double result = num2/num1;
                    stack.push(result);
                    break;
                }
                default: {
                    Double in = Double.parseDouble(expression[i]);
                    stack.push(in);
                }
            }
        }
        System.out.println(stack.pop());
    }

总结

以上就是利用Java语言处理中缀表达式和后缀表达式,实现计算功能的过程。在Java中处理问题时,会产生一些独有想法和实现方式,不妨再继续动手试一试?

以下是一个示例代码,可以输入一串算式并返回计算结果: ``` import java.util.Scanner; public class Calculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入算式:"); String expression = scanner.nextLine(); int result = calculate(expression); System.out.println("计算结果为:" + result); } public static int calculate(String expression) { // 去掉空格 expression = expression.replaceAll(" ", ""); // 定义两个,一个存储数字,一个存储运算符 Stack<Integer> numStack = new Stack<>(); Stack<Character> opStack = new Stack<>(); // 遍历表达 for (int i = 0; i < expression.length(); i++) { char c = expression.charAt(i); if (Character.isDigit(c)) { // 如果是数字,将其压入数字 int num = c - '0'; while (i + 1 < expression.length() && Character.isDigit(expression.charAt(i + 1))) { num = num * 10 + expression.charAt(i + 1) - '0'; i++; } numStack.push(num); } else if (c == '(') { // 如果是左括号,将其压入运算符 opStack.push(c); } else if (c == ')' || c == '+' || c == '-' || c == '*' || c == '/') { // 如果是右括号或运算符 while (!opStack.isEmpty() && opStack.peek() != '(' && priority(opStack.peek()) >= priority(c)) { // 如果运算符顶的运算符优先级不低于当前运算符,则弹出运算符和两个数字进行运算 int num2 = numStack.pop(); int num1 = numStack.pop(); char op = opStack.pop(); int result = operate(num1, num2, op); numStack.push(result); } if (c == ')') { // 如果是右括号,弹出左括号 opStack.pop(); } else { // 如果是运算符,将其压入运算符 opStack.push(c); } } } // 将剩余的运算符和数字依次弹出进行运算 while (!opStack.isEmpty()) { int num2 = numStack.pop(); int num1 = numStack.pop(); char op = opStack.pop(); int result = operate(num1, num2, op); numStack.push(result); } return numStack.pop(); } // 定义运算符优先级 public static int priority(char op) { switch (op) { case '+': case '-': return 1; case '*': case '/': return 2; default: return 0; } } // 定义运算方法 public static int operate(int num1, int num2, char op) { switch (op) { case '+': return num1 + num2; case '-': return num1 - num2; case '*': return num1 * num2; case '/': return num1 / num2; default: return 0; } } } ``` 使用示例: ``` 请输入算式:(1+2)*3+4*(5-6) 计算结果为:-2 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醉倾梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值