题目叙述:
有一组小学生要开始学习算术运算,需要使用计算机辅助他们检查计算结果,请帮助小同学设计一个能够完成+、-、*、\、幂运算和阶乘的计算器程序
具体要求:
- 由于是面向小同学的软件工具,请设计一个友好、方便的用户交互界面
- 计算器应该能够完成由加、减、乘、除运算符构成的复合算术表达式的求解,允许使用括号
- 计算器能够完成幂运算和阶乘运算,其中,幂运算可以采用M^N的方式输入
提前说明:
- 该程序由一个类实现,可通过调用solve方法求解,具体使用方式请看main函数
- 程序缺少必要注释,本博客未列出求解思路,具体查看源码
- 该程序未实现单独负数的处理,如
-1-2
或者2^-2
等 - 支持浮点数,但未使用大数,程序可能会产生溢出
运行示例:
程序源码:
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));
}
}