当输入算式为字符串时,需要判断其计算优先级,本算法基于栈设计,可以处理括号,加减乘除以及次方运算。
算法如下
import java.util.HashMap;
import javatest.myStack;
public class zisushuru_jisuan {
// public static ArrayList<HashMap<Character,Integer>> character = new ArrayList<HashMap<Character,Integer>>();
public static HashMap<String,Integer> temp = new HashMap<String,Integer>();
public static void main(String[] args){
initpriority();
System.out.println("结果:"+calculate("(1+2)*4-(4-2)^3"));
}
static void initpriority(){
/*
* 此处设置运算符的优先级,数值越大,优先级越高
* 分为两个栈,运算符栈和运算数栈,
* 逻辑:1、当前读取的运算符优先级高于运算符栈的优先级,直接入栈
* 若低于等于当前优先级则运算符栈弹出一个运算符,运算数栈弹出两个运算数,三者进行运算,
* 结果压入运算数栈,重复这个过程,直至读取的运算符优先级大于运算符栈栈顶的元素或者运算符栈为空,
* 此时将次运算符压入栈中。
* 2、若遇到左括号,直接入栈。
* 3、若遇到右括号,则将运算符栈中左括号以上的运算符依次进行弹出并运算,最后将左括号也弹出。
* 4、遇到操作数,直接入操作数栈。
* */
temp.put("(",0);
temp.put(")",4);
temp.put("+", 1);
temp.put("-", 1);
temp.put("*", 2);
temp.put("/", 2);
temp.put("^", 3);
}
public static char[] toArray(String input){
return input.toCharArray();
}
static String calculate(String input){
myStack in = new myStack(); //输入字符串储存栈
myStack operand = new myStack(); //操作数栈
myStack operator = new myStack(); //操作符栈
char[] ch = toArray(input);
for(int i=ch.length-1;i>=0;i--){
in.push(String.valueOf(ch[i]));
} //初始化字符储存栈
/*
* 此处初始化操作符和操作数两个栈,假设输入的字符串是正确的,则前两个字符
* 必一个是操作数,一个是操作符。
* */
if(in.isnum(in.peek())){
operand.push(in.getNext());
operator.push(in.getNext());
}else{
operator.push(in.getNext());
operand.push(in.getNext());
}
String temp1="";
while(!in.isEmpty()||!operator.isEmpty()){
/*
* 直至输入字符串和操作符都为空才结束
* 此时操作数栈只有一个元素,即为计算结果。
* */
if(in.isEmpty()){
/*
* 输入字符串为空,则不必继续读入,直接进行计算
* */
while(!operator.isEmpty()){
String aa = result(operator.pop(),operand.pop(),operand.pop());
operand.push(aa);
}
return operand.pop();
}
temp1 = in.getNext();
//System.out.println(" temp1:"+temp1);
if(in.isnum(temp1)){ //判断是否为数字
operand.push(temp1);
}else if(operator.isEmpty()){ // 操作符栈是否为空
operator.push(temp1);
continue;
}else if(temp1.equals("(")){ //是否为左括号
operator.push("(");
}else if(temp1.equals(")")){ //是否为右括号
while(!operator.peek().equals("(")){ //计算
String aa = result(operator.pop(),operand.pop(),operand.pop());
operand.push(aa);
}
operator.pop();
continue;
}else if(temp.get(temp1)>temp.get(operator.peek())){ //当前字符优先级高于操作符栈顶优先级
operator.push(temp1);
continue;
}else if(temp.get(temp1)<=temp.get(operator.peek())){ //当前字符优先级低于等于操作符栈顶优先级
while(!operator.isEmpty()&&temp.get(temp1)<=temp.get(operator.peek())){
String aaa = result(operator.pop(),operand.pop(),operand.pop());
operand.push(aaa);
}
operator.push(temp1);
continue;
}
}
return operand.pop(); //返回结果
}
static String result(String operator,String b,String a){ //计算函数,可增加
switch(operator){
case "+": return Double.toString(Double.parseDouble(a)+Double.parseDouble(b));
case "-": return Double.toString(Double.parseDouble(a)-Double.parseDouble(b));
case "*": return Double.toString(Double.parseDouble(a)*Double.parseDouble(b));
case "/": return Double.toString(Double.parseDouble(a)/Double.parseDouble(b));
case "^": return Double.toString(Math.pow(Double.parseDouble(a),Double.parseDouble(b)));
}
return null;
}
}
此处为自定义的栈继承了Stack,添加了getNext方法,和isnum方法,getNext()方法用于从输入字符栈中取出一整个操作数或者操作符。比如若操作数是两位以上,则需要弹栈多次直至遇到操作符。
public class myStack extends Stack<String> {
String getNext(){ //获取输入字符栈的首元素,若为一连串数字,则全部取出直至遇到操作符
if(!this.isEmpty()){
String temp = "";
if(isnum(this.peek())){
while(!this.isEmpty()&&isnum(this.peek())){
temp+=this.pop();
}
return temp;
}
return this.pop();
}
return null;
}
boolean isnum(String a){ //判断是否为数字
for(int j=0;j<a.length();j++){
if(!Character.isDigit(a.charAt(j))&&!(a.charAt(j)=='.')){
return false;
}
}
return true;
}
}
运行结果