使用Java求数学表达式的值

关于怎么求数学表达式的值,网上有很多教程。但大多教程只是一个Demo,该Demo只实现了个位数的四则运算,遇到个位数以上的计算时就会出现问题。本文在此基础上进行了扩展,实现了个位数以上的四则运算。

整体思路:

输入的表达式为中缀表达式,将该表达式转为后序表达式然后利用栈做运算。

中缀表达式转后缀表达式的方法:(用list存放后缀表达式中各元素,用栈stack临时存放运算符)

1:遇到数字时:将其放入list。

2:遇到运算符时:当运算符时乘号或者除号时直接入栈。当运算符时加减号时:若栈为空则直接入栈;否则,获取栈顶运算符topOper(是获取,而不是弹出,故用peek而不是pop),若topOper为左括号时,直接入栈,否则循环获取栈中左括号上面的元素加入list,最后将当前运算符入栈。

3:遇到左括号(“(”)时,直接入栈;

4:遇到右括号时(“)”),依次出栈,当出栈运算符为左括号时,退出。

5:最终将栈中的各元素依次出栈放入list。

使用后缀表达式求值的方法:

依次遍历list中的各元素进行入栈,当得到的元素为运算符时,取出栈顶的两个元素做运算,然后将运算结果入栈,直到list遍历完成。

代码如下:

import java.util.*;

public class MyStackCalculators {

	public static void main(String[] args) {

		String string = "(7+4*3+10*(3-3+4-1-8-10))";
		List<String> inputList = strToList(string);
		List<String> postfix = getPostfixExpression(inputList);
		String res = getRes(postfix);
		System.out.println("最终结果为:" + res);
	}
	
	/**
	 * 获取输入表达式中的各元素,并用list进行存储。
	 * @param expression
	 * @return
	 */
	private static List<String> strToList(String expression) {

		List<String> arrayList = new ArrayList<String>();
		char ch[] = expression.toCharArray();
		String v = "";
		for(int i=0; i<ch.length; i++) {
			char e = ch[i];
			if(e >= '0' && e <= '9') {
				v += e;
			} else {
				if(v != "") {
					arrayList.add(v);
				}
				arrayList.add(e + "");
				v = "";
			}
		}
		if(v != "") {
			arrayList.add(v);
		}
		return arrayList;
	}
	
	private static List<String> getPostfixExpression(List<String> list) {

		List<String> pfixExpList = new ArrayList<>();//存放后缀表达式中各元素的list
		Stack<String> stack = new Stack<>();//存放运算符的栈
		for(int i=0; i<list.size(); i++) {
			String tm = list.get(i);
			if(tm.matches("[0-9]*")) {//当得到的元素是数字时,直接放入list。
				pfixExpList.add(tm);
			} else if(tm.equals("(")) {//当得到元素是左括号时,直接入栈
				stack.push(tm);
			} else if(tm.equals(")")){//当得到元素是右括号时
				//执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
				String s = stack.pop();
				while(!(s.equals("(")) && !stack.isEmpty()) {
					pfixExpList.add(s);
					s = stack.pop();//此语句最终会弹出左括号
				}
			} else { //是运算符
				if(tm.equals("*") || tm.equals("/")) { //乘号和除号情况,直接入栈
					stack.push(tm);
				} else {//加减号情况,取出栈中的“(”上面的全部元素存入list1,最后将当前运算符入栈
					if(stack.isEmpty()) {
						stack.push(tm);
					} else {
						String s = stack.peek();
						if(s.equals("(")) {
							stack.push(tm);
						} else {
							while(!s.equals("(") && !stack.isEmpty()) {
								pfixExpList.add(stack.pop());
								s = stack.peek();
							}
							stack.push(tm);//将当前运算符入栈
						}
					}
				}
			}
		}
		//将栈中剩余元素存入list
		while(!stack.isEmpty()) {
			pfixExpList.add(stack.pop());
		}
		return pfixExpList;
	}

	/**
	 * 得到表达式的最终值
	 * @param list 存放的后缀表达式各元素
	 * @return
	 */
	private static String getRes(List<String> list) {

		Stack<String> stack = new Stack<String>();//存放结果用
		for(int i=0; i<list.size(); i++) {
			String el = list.get(i);
			if(el.matches("[0-9]*")) {//若为数字,直接入栈。
				stack.push(el);
			} else {//若不为数字,则取出栈顶的两个元素做运算,并将结果入栈
				int v1 = 0;
				int v2 = 0;
				int res = 0;
				switch(el) {
				case "+":
					v2 = Integer.valueOf(stack.pop());
					v1 = Integer.valueOf(stack.pop());
					res = (v1 + v2);
					stack.push(res+"");
					break;
				case "-":
					v2 = Integer.valueOf(stack.pop());
					v1 = Integer.valueOf(stack.pop());
					res = (v1 - v2);
					stack.push(res+"");
					break;
				case "*":
					v2 = Integer.valueOf(stack.pop());
					v1 = Integer.valueOf(stack.pop());
					res = (v1 * v2);
					stack.push(res+"");
					break;
				case "/":
					v2 = Integer.valueOf(stack.pop());
					v1 = Integer.valueOf(stack.pop());
					res = (v1 / v2);
					stack.push(res+"");
					break;
				}
			}
		}
		return stack.pop();
	}
}

运行结果如下:

最终结果为:-131

注:关于这代码还有一个问题就是当表达式中有乘和除连续的时候,是按照其出现的顺序计算的,这会导致1/3*3为0的情况。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值