【java】java实现简单计算器

最近在学java,视频教程中留了个小作业,说是要做个简单计算器。但是我突然心血来潮,想整个更花里胡哨的,能计算稍微复杂一点的表达式的计算器。

要达到的功能:

(1000-(5*5*9+10)*8)*10/100
>> -88

代码如下

package com.huang.method;

import java.util.Scanner;
import java.util.Stack;

/**
 * @author huangwentao
 * @date 2021/10/19 20:22
 * @description 简单计算器
 */
public class Computer {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            System.out.println(compute(line));
        }
        scanner.close();
    }

    /**
     * 计算字符串表达式
     * @param expression 表达式
     * @return double 计算值
     */
    public static double compute(String expression) {
        // 将表达式切割
        String[] list = splitExpression(expression);
        Stack<string> st = new Stack<>();
        // 依次将表达式入栈
        for (String s : list) {
            // 如果遇到')',该段表达式结束
            if (s.equals(")")) {
                // 暂存栈
                Stack<string> st1 = new Stack<>();
                // 取出表达式到离该')'最近的'('
                while (!st.empty()) {
                    String item = st.pop();
                    if (item.equals("(")) {
                        st.push(computeStack(st1));
                        break;
                    }
                    st1.push(item);
                }
            } else
                st.push(s);
        }

        // 暂存栈
        Stack<string> st1 = new Stack<>();
        while (!st.empty()) {
            st1.push(st.pop());
        }
        // 计算表达式栈得到最终结果
        return Double.valueOf(computeStack(st1));
    }

    /**
     * 计算栈内表达式的值
     *
     * @param st 表达式栈(无括号)
     * @return double 计算结果
     */
    public static String computeStack(Stack<string> st) {
        // 暂存栈
        Stack<string> st1 = new Stack<>();
        // 计算乘除
        while (!st.empty()) {
            String item = st.pop();
            // 如果为乘除,则计算
            if ("*/".contains(item)) {
                double left = Double.valueOf(st1.pop());
                double right = Double.valueOf(st.pop());
                // 计算结果
                String result = (item.equals("*") ? left * right : left / right) + "";
                // 将计算结果加入st1
                st1.push(result);
            } else
                st1.push(item);
        }

        // 栈反转(因为此时出栈的话,表达式计算顺序是反的)
        st = new Stack<>();
        while (!st1.empty())
            st.push(st1.pop());

        // 计算加减(此时st1为空栈)
        while (!st.empty()) {
            String item = st.pop();
            // 如果为加减,则计算
            if ("+-".contains(item)) {
                double left = Double.valueOf(st1.pop());
                double right = Double.valueOf(st.pop());
                // 计算结果
                String result = (item.equals("+") ? left + right : left - right) + "";
                // 将计算结果加入st1
                st1.push(result);
            } else
                st1.push(item);
        }
        // 栈中剩下的最后一个为结果
        return st1.pop();
    }

    /**
     * 使用占位符'|'切割表达式
     *
     * @param expression 表达式
     * @return String[] 切割后的结果
     */
    public static String[] splitExpression(String expression) {
        // 移除表达式中的占位符和空格(如有)
        expression = expression.replaceAll("[| ]", "");
        // 将表达式符号两边加|,如1+1 -> 1|+|1
        expression = expression.replaceAll("([+\\-*/()])", "|$1|");
        // 将连着的||替换为|,如1+(2) -> 1|+||(|2|)| -> 1|+|(|2|)|
        expression = expression.replaceAll("\\|\\|", "|");
        // 移除首尾的|(如有)
        expression = expression.replaceAll("(^\\||\\|$)", "");
        // 通过|切割
        return expression.split("\\|");
    }
}

结果演示

QQ图片20211019221233

遗留问题

  • 目前代码无法计算+-开头的表达式,如+2-2
  • 括号内的表达式不能以+-开头,如(+2)(-2+1)

以上问题是computeStack函数的内部缺陷,有机会再解决吧。

posted @ 2021-10-19 22:17  ぃ往事深处少年蓝べ  阅读(74)  评论(0编辑  收藏  举报