简易计算器,可实现任意长度带括号带优先级的 ‘加减乘除幂’ 运算
还未加入报错机制,需要求表达式书写正确,不能存在左右括号数目不等或右括号前没有数字或除数为0等情况
/*
科学计算器,可实现任意长度带括号带优先级的 '加减乘除幂' 运算
还未加入报错机制,需要求表达式书写正确,不能存在左右括号数目不等或右括号前没有数字或除数为0等情况
*/
import java.util.Hashtable;
import java.util.Stack;
public class ScientificCalculator {
public static double calc(double a, double b, char operator){
switch (operator){
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
case '^':
return Math.pow(a,b);
}
return 0.0d;
}
//出栈两个操作数,一个操作符,运算结果入操作数 需重复运算,所以写成一个函数
public static void calcTwo(Stack<Double> stack1, Stack<Character> stack2){
double a = 0.0d;
double b = 0.0d;
double c = 0.0d;
char ope = ' ';
b = stack1.pop(); //出栈两个操作数一个操作符,运算结果入栈
a = stack1.pop();
ope = stack2.pop();
c = calc(a,b,ope);
stack1.push(c);
}
/*规则:
*依次处理每个字符
*1.是数字则暂存起来
*2.是左括号压入堆栈
*3.是右括号则运算至操作符栈顶为左括号
*4.是运算符:
* 将暂存的字符压入数字栈
* 若优先级大于栈顶运算符 或 运算符栈为空 或 栈顶运算符为左括号,压入栈
* 若优先级小于或等于栈顶运算符,弹出两个数进行计算
*5.对象处理完毕后,计算栈中元素直至栈空
*/
public static double scientificCalculate(String str){
Stack<Double> num_stack = new Stack<>(); //操作数栈
Stack<Character> sym_stack = new Stack<>(); //操作符栈
int num_brackets = 0; //括号层数
Hashtable<Character,Integer> pri_map = new Hashtable<>();//操作符优先级
pri_map.put('+', 0);
pri_map.put('-', 0);
pri_map.put('*', 1);
pri_map.put('/', 1);
pri_map.put('^', 2);
pri_map.put('(', 0);
pri_map.put(')', 0);
double result = 0.0d;
String res = "";
double res_trans = 0.0d; //字符串转double类型
for(int i = 0 ;i < str.length();i++){
if((str.charAt(i) != '+') && (str.charAt(i) != '-') && (str.charAt(i) != '*') && (str.charAt(i) != '/' && (str.charAt(i) != '^') && (str.charAt(i) != '(') && (str.charAt(i) != ')'))){
res += str.charAt(i);
}
//当前元素为运算符
else if((str.charAt(i) == '+') || (str.charAt(i) == '-') || (str.charAt(i) == '*') || (str.charAt(i) == '/') || (str.charAt(i) == '^')){
if(str.charAt(i-1) != ')') {
res_trans = Double.valueOf(res); //操作数入栈
num_stack.push(res_trans);
res = "";
}
//操作符栈为空 或 当前运算符优先级大于栈顶运算符优先级 或 操作符栈顶元素为左括号 ,则操作符入栈
if((sym_stack.empty()) || (pri_map.get(str.charAt(i))>pri_map.get(sym_stack.peek())) || (sym_stack.peek() == '(')){
sym_stack.push(str.charAt(i));
}else{
calcTwo(num_stack,sym_stack);
sym_stack.push(str.charAt(i));
}
}
//如果是左括号则入操作符栈
else if(str.charAt(i) == '('){
sym_stack.push(str.charAt(i));
num_brackets ++;
}
//如果是右括号则运算至操作符栈顶为左括号
else if(str.charAt(i) == ')'){
if(str.charAt(i-1) != ')') {
res_trans = Double.valueOf(res); //操作数入栈
num_stack.push(res_trans);
res = "";
}
if(sym_stack.peek() == '('){
sym_stack.pop();
num_brackets--;
}else{
do{
calcTwo(num_stack,sym_stack);
}while(sym_stack.peek() != '(');
sym_stack.pop();
num_brackets--;
}
}
}
if(res != "") {
res_trans = Double.valueOf(res); //操作数入栈
num_stack.push(res_trans);
}
calcTwo(num_stack,sym_stack);
//一直运算至操作符栈为空
while(!sym_stack.empty()){
calcTwo(num_stack,sym_stack);
}
result = num_stack.peek();
return result;
}
public static void main(String[] args) {
System.out.println("科学计算器,可实现任意长度带括号带优先级的‘+-*/幂'运算");
double result1 = scientificCalculate("(5.2*6*3+(5+5)*2)*3");
System.out.println(result1);
double result2 = scientificCalculate("3*(5+6*3+5*5^2)");
System.out.println(result2);
double result3 = scientificCalculate("(1+2)*(5+6*(1+2)+5*5^2)");
System.out.println(result3);
}
}
来源:CSDN
作者:qq_34623223
链接:https://blog.csdn.net/qq_34623223/article/details/104573113