Java实现能完成 加减乘除幂与阶乘 组合运算的计算器

题目叙述:

有一组小学生要开始学习算术运算,需要使用计算机辅助他们检查计算结果,请帮助小同学设计一个能够完成+、-、*、\、幂运算和阶乘的计算器程序


具体要求:

  1. 由于是面向小同学的软件工具,请设计一个友好、方便的用户交互界面
  2. 计算器应该能够完成由加、减、乘、除运算符构成的复合算术表达式的求解,允许使用括号
  3. 计算器能够完成幂运算和阶乘运算,其中,幂运算可以采用M^N的方式输入

提前说明:

  1. 该程序由一个类实现,可通过调用solve方法求解,具体使用方式请看main函数
  2. 程序缺少必要注释,本博客未列出求解思路,具体查看源码
  3. 该程序未实现单独负数的处理,如-1-2 或者 2^-2
  4. 支持浮点数,但未使用大数,程序可能会产生溢出

运行示例:

test1
test2


程序源码:

package experiment;

import javafx.util.Pair;

import java.util.*;

public class Calculator {
    private final Stack<Double> numSt;
    private final Stack<Character> opSt;

    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        System.out.print("Please input: ");
        Scanner in = new Scanner(System.in);
        String str = in.nextLine();
        System.out.println("The answer is: " + calculator.solve(str));
    }

    public Calculator() {
        numSt = new Stack<>();
        opSt = new Stack<>();
    }

    // 求解表达式并返回值
    public double solve(String in) {
        String evalStr = in.trim();
        for (int i = 0; i < evalStr.length(); ++i) {
            char ch = evalStr.charAt(i);
            if (ch >= '0' && ch <= '9') {
                Pair<Double, Integer> res = parseNum(evalStr, i);
                numSt.push(res.getKey());
                i = res.getValue();
            } else if (ch == '(') {
                opSt.push('(');
            } else if (ch == ')') {
                while (!opSt.empty() && opSt.peek() != '(') {
                    opNum();
                }
                opSt.pop();
            } else if (ch == '!') {
                // 阶乘运算符注意溢出
                int top = numSt.pop().intValue();
                numSt.push((double) factorial(top));
            } else {
                if (!opSt.empty() && cmpPriority(opSt.peek(), ch)) {
                    while (!opSt.empty() && cmpPriority(opSt.peek(), ch)) {
                        opNum();
                    }
                }
                opSt.push(ch);
            }
        }
        while (!opSt.empty()) {
            opNum();
        }
        return numSt.peek();
    }

    // 解析字符串,返回整数.返回结果是键值对,键是解析结果,值是解析完成指向的位置
    private static Pair<Double, Integer> parseNum(String num, int start) {
        int end = start;
        while ((num.charAt(end) >= '0' && num.charAt(end) <= '9') || num.charAt(end) == '.') {
            ++end;
            if (end >= num.length()) break;
        }
        return new Pair<>(Double.parseDouble(num.substring(start, end)), end - 1);
    }

    // 比较操作符优先级,若前者优先级比较大则返回true,否则返回false
    private boolean cmpPriority(char x, char y) {
        if (x == '^') {
            return true;
        } else if (x == '*' || x == '/') {
            return y != '^';
        } else if (x == '+' || x == '-') {// 否则x就只能是"+"或"-"
            return y == '+' || y == '-';
        } else {
            return false;
        }
    }

    // 求一个数的阶乘
    private long factorial(int x) {
        if (x < 1) return 1;
        long res = 1;
        for (int i = 2; i <= x; ++i) {
            res *= i;
        }
        return res;
    }

    // 对两个栈执行操作,确保调用时操作符栈非空,操作数栈内容至少为2
    private void opNum() {
        char op = opSt.pop();
        Double x = numSt.pop();
        if (op == '+') numSt.push(numSt.pop() + x);
        else if (op == '-') numSt.push(numSt.pop() - x);
        else if (op == '*') numSt.push(numSt.pop() * x);
        else if (op == '/') numSt.push(numSt.pop() / x);
        else if (op == '^') numSt.push(Math.pow(numSt.pop(), x));
    }
}

你可能感兴趣的:(习题,java,栈)