参考文献
https://www.cnblogs.com/lulipro/p/7450886.html
https://www.cnblogs.com/tangyihengloveleishunyue/p/10613757.html
https://blog.csdn.net/qq_41398808/article/details/79558789
1.功能
支持的操作数:正整数和正小数
支持的运算符:+-*/
支持的隔离符:()
2.步骤
输入:表达式字符串(如:6*(5-2)-9/3)
输出:表达式的计算结果
步骤一:将表达式字符串划分为操作数、操作符、隔离符存在数组
步骤二:使用逆波兰算法,将步骤一划分后的中缀表达式转化为后缀表达式
步骤三:根据后缀表达式,计算结果
3. 步骤一:表达式字符串划分
(1)新建ArrayList数组,
(2)从左到右,遍历字符串的每一个字符。
如果是数字,则继续向后遍历,直至遇到不是数字的字符或者表达式结束。将整个数字加入到list中。
如果是其余字符,则将其单个字符加入到list中
4.步骤二:中缀表达式转后缀表达式
(1)需要一个栈stack,一个ArrayList类型的list
(2)遍历步骤一的ArrayList数组
如果是数字,加入到list中,
如果是左括号,则加入到stack中
如果是右括号,则丢弃,将stack中从栈顶到(的部分依次放入到list中。左括号同样丢弃
如果是操作符,if此时栈顶同样是操作符,并且栈顶操作符的优先级比较高,则将栈顶操作符弹出到list中。并重复上述比较。(比如:如果是栈顶元素是“-”,要放入的是“*”,就可以放。如果栈顶元素是“*”,要放入的是“-”,则需要将“*”放入list中,再继续将栈顶元素和“-”比较。)
注意:不能出现连续的同级操作符,如果遇到,弹栈,放入到list中
(3)遍历结束后,如果stack中还有元素,则从栈顶开始,依次加入到list中
5. 步骤三:后缀表达式计算结果
(1)需要一个栈stack
(2)遍历步骤二中的list,
如果是数字加入到stack中;
如果是操作符,则将栈中顶端的两个元素弹出,进行操作符的运算后,将计算结果放入栈中。(如栈中的元素为6 5 3,栈顶元素为3,操作符为“-”,则将3和5弹出,计算5-3=2,将2压入栈中,此时栈中的元素为6 2)
6. 用到的函数
String.valueof():将double类型的浮点数转换为字符串
Double.parseDouble():将字符串转化为double类型的浮点数
7. 源代码
Element类:包含值和优先级,如“+”的优先级是1。“*”的优先级是2。
public class Element {
public Element(String val,int pri)
{
this.value=val;
this.priority=pri;
}
public Element() {};
private String value;
private int priority;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
}
主函数:
import java.util.Scanner;
import java.util.Stack;
import java.util.ArrayList;
/*
* 计算器,能够实现+-*÷()功能
*/
public class Computer {
@SuppressWarnings("resource")
public static void main(String[] args)
{
//读取用户输入的表达式,转化为字符串
Scanner input =new Scanner(System.in);
String str=input.nextLine();
//分离表达式,并测试输出
ArrayList<Element> inOrderArrays=strToArrays(str);
for(int i=0;i<inOrderArrays.size();i++)
{
System.out.println(inOrderArrays.get(i).getValue());
}
//将中缀表达式转换为后缀表达式
ArrayList<Element> postOrderArrays=toPostArrays(inOrderArrays);
for(int i=0;i<postOrderArrays.size();i++)
{
System.out.println(postOrderArrays.get(i).getValue());
}
//计算后缀表达式,得出结果值
String result=getResult(postOrderArrays);
System.out.println(str+"="+result);
}
//将表达式字符串分离,划分操作数、操作符、隔离符
//操作数权重为0,加减为1,乘除为2,小括号为3
public static ArrayList<Element> strToArrays(String str)
{
ArrayList<Element> arr=new ArrayList<Element>();
int len=str.length();
for(int i=0;i<len;i++)
{
if(str.charAt(i)=='+'|| str.charAt(i)=='-' )
{
//+-优先级为1
Element ele=new Element(str.substring(i,i+1),1);
//ele.setValue(str.substring(i,i+1));
//ele.setPriority(1);
arr.add(ele);
}
else if(str.charAt(i)=='*'|| str.charAt(i)=='/')
{
//乘除优先级为2
Element ele=new Element(str.substring(i,i+1),2);
//ele.setValue(str.substring(i,i+1));
//ele.setPriority(2);
arr.add(ele);
}
else if(str.charAt(i)=='('|| str.charAt(i)==')')
{
//乘除优先级为2
Element ele=new Element(str.substring(i,i+1),3);
//ele.setValue(str.substring(i,i+1));
//ele.setPriority(3);
arr.add(ele);
}
else if(isNum(str.charAt(i)))
{
int now=i;
while(now<len && isNum(str.charAt(now)))
{
now++;
}
Element ele=new Element(str.substring(i,now),0);
//ele.setValue(str.substring(i,now));
//ele.setPriority(0);
arr.add(ele);
i=now-1;
}
else {
System.out.println(str+" "+i+" 表达式有误");
}
}
return arr;
}
//判断该字符是否为数字
public static boolean isNum(char c)
{
if(c<='9'&& c>='0' || c=='.')
{
return true;
}
else
{
return false;
}
}
//转为后缀表达式
public static ArrayList<Element> toPostArrays(ArrayList<Element> arr)
{
ArrayList<Element> list=new ArrayList<Element>();
Stack<Element> st = new Stack<Element>();
for(int i=0;i<arr.size();i++)
{
System.out.println(arr.get(i).getValue());
switch(arr.get(i).getPriority())
{
case 0:
//如果是数字
list.add(arr.get(i));
break;
case 1:
//如果是加减,需要判断栈顶元素,如果是乘除,需要将栈顶元素输出,继续和下一个栈顶元素比较,直至优先级相等,或者是()
while(!st.isEmpty()&& st.peek().getPriority()==2)
{
list.add(st.peek());
st.pop();
}
st.push(arr.get(i));
break;
case 2:
//如果是乘除,就可以直接压入栈中
st.push(arr.get(i));
break;
case 3:
//如果是左括号,添加到栈中;如果是右括号,将栈中左括号之前的元素都弹出;
if(arr.get(i).getValue().equals("("))
{
st.push(arr.get(i));
}
else
{
//System.out.println(st.peek().getValue());
while(!st.peek().getValue().equals("("))
{
Element ele=st.pop();
list.add(ele);
}
st.pop();
}
break;
default:
System.out.println("中缀转后缀失败");
break;
}
}
while(!st.isEmpty())
{
list.add(st.pop());
}
return list;
}
//根据后缀表达式计算结果
public static String getResult(ArrayList<Element> arr)
{
String res="";
Stack<String> st=new Stack<String>();
for(int i=0;i<arr.size();i++)
{
switch(arr.get(i).getPriority())
{
case 0:
//如果是数字,放进栈中
st.push(arr.get(i).getValue());
break;
case 1:
case 2:
//如果 是操作符,将栈中两个元素弹出,进行计算,并将结果放入栈中
double secondNum=Double.valueOf(st.pop());
double firstNum=Double.valueOf(st.pop());
double resultNum=compute(firstNum,secondNum,arr.get(i).getValue());
st.push(String.valueOf(resultNum));
break;
default:
break;
}
}
res=st.pop();
if(!st.isEmpty())
{
System.out.println("计算有误");
return "error";
}
return res;
}
//给定两个操作数,和一个操作符,计算结果
public static double compute(double a,double b,String op)
{
double res=0;
switch(op)
{
case "+":
res=a+b;
break;
case "-":
res=a-b;
break;
case "*":
res=a*b;
break;
case "/":
case "÷":
res=a/b;
break;
default:
res=9999999;
}
return res;
}
}