【java】逆波兰算法实现简易计算器

参考文献

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;
	}
}

    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值