Java GUI实现的计算器(中缀转后缀,运算有顺序)
1、问题描述
本程序支持含负数、小数、多位数等多种操作数的处理,可以计算含加、减、乘、除、求余、求幂等多种运算符(“+”、“-”、“*”、“/”)的表达式,并能判断表达式括号是否匹配;从键盘输入一个正确的中缀表达式,将中缀表达式转换为计算机理解的后缀表达式,计算后缀表达式(运算有顺序)的值。
GUI计算器实现对于表达式中的简单错误,能够给出提示信息的弹窗,且不允许错误信息进入表达式;
(2)能够处理多种操作符
(3)实现包含简单运算的计算器
2、算法实现
中缀表达式转为后缀表达式
①我们使用一个stack栈结构存储操作符,用一个List结构存储后缀表达式结果,使用map结构来判断运算符的优先级;
②首先读取到数字,直接存入list中;
③当读取到左括号"("时,直接压栈,当读取到运算符时,分两种情况讨论;
-
运算符栈为空,直接入栈
-
当栈顶操作符的优先级 小于 当前运算符优先级时(如+和-的优先级低于 * 和 /),直接入栈;
-
当运算符不为空 且 栈顶操作符的优先级 大于或等于 当前运算符优先级时,循环执行出栈操作并加入list中,直到遇到优先级小于当前运算符的元素为止。循环执行完后再将当前运算符压栈。
PS. 只有遇到右括号时,左括号才出栈;
④当遇到右括号")"时,循环执行出栈操作并加入到list中,直到遇到左括号为止。并将左括号弹出,但不加入list中;
⑤表达式的值读取完后,将操作符栈中的所有元素弹出并加入到list中;
执行完上面步骤后,list中存储的顺序即为我们转换后的后缀表达式的结果
//中缀表达式转后缀表达式
public void evalRPN() {
Stack<String> stack = new Stack<>();
Iterator<String> iterator = expression.iterator();
while(iterator.hasNext()) {
String now = iterator.next();
System.out.println(now);
if(isNumeric(now)) {
suffix.add(now);//数字直接入list
}else{
if(stack.isEmpty()) {
//判断栈是否为空
stack.add(now);
continue;
}
if(now.equals("(")) {
//括号判断,分情况
stack.add(now);
}else if(now.equals(")")) {
while(true) {
if(stack.peek().equals("(")) {
stack.pop();
break;
}else{
suffix.add(stack.pop());
}
}
}else{
if(map.get(stack.peek()) < map.get(now) || (stack.peek()).equals("(")) {
stack.add(now);
}else{
while(true) {
suffix.add(stack.pop());
if(stack.isEmpty() == true ||map.get(stack.peek()) < map.get(now)) {
stack.add(now);
break;
}
}
}
}
}
}
suffix.add(stack.pop());
}
碎碎念:迭代器挺好用的
Iterator()方法
无论List、Set、Queue,都有个iterator()方法,定义在Collection接口中,而这些线性表和集合都是继承自Collection接口。iterator()方法会返回java.util.Iterator接口的操作对象(Collection收集的所有对象)。
static void forEach(Collection collection) {
//借forEach函数来展示迭代器方法
Iterator iterator = collection.iterator();
while(iterator.hasNext()) {
out.println(iterator.next());
}
}
常用方法
Iterator= list.iterator()
将集合list变成迭代器it,接下来就可以操作迭代器的方法了it.hasNext()
查看是否还有下一个元素it.next()
查看一个元素it.remove()
删除当前元素并返回
后缀表达式计算结果
将数字存入stack结构中,从右向左看,遇到运算符则使用stack.pop弹出最上面的两个数字,运算之后将结果压栈。持续往复,直到读取完表达式,此时栈内剩余的最后一个数值,即为后缀表达式的运算结果。
//后缀表达式计算结果
public void Calculate() {
Stack<Double> stack = new Stack<>();
for(int i = 0; i < suffix.size(); i++){
String item = suffix.get(i);
if(isNumeric(item)){
//是数字
stack.push(Double.parseDouble(item));
}else {
//是操作符,取出栈顶两个元素
Double num2 = stack.pop();
Double num1 = stack.