【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("\\|");
}
}
结果演示
遗留问题
- 目前代码无法计算
+-
开头的表达式,如+2
、-2
等 - 括号内的表达式不能以
+-
开头,如(+2)
、(-2+1)
以上问题是computeStack
函数的内部缺陷,有机会再解决吧。