(算法)java完成解析数学算式(计算器)一 —— 递归、正则直接遍历字符串解析

一、程序要求

解析一般数学算式,实现简单的带括号的加减乘除运算。

二、基本思路

先从我们人的角度,考虑平时在计算一个式子的思路,任意假设一个的数学表达式-3.5*(4.5-(4+(-1-1/2)))

  • 1、计算最里面的括号(最后一个左括号)里的表达式(-1-1/2)
  • 2、计算除法1/2,将括号内容变为(-1-0.5)
  • 3、计算减法,得出括号结果-1.5
  • 4、用该结果将括号替换,表达式变为-3.5*(4.5-(4±1.5))
  • 5、重复1-4步,去掉剩下的两个括号,将表达式变为-3.5*2
  • 6、算一步乘法,得-7,除了首位正负号外,不含其它符号,即运算结束,-7为运算结果

简单总结,即**先去括号至无括号,再去乘除至无乘除,最后去加减至无加减**,以此思路编写程序如下,结合注释分析具体步骤:

三、代码

环境:

  • Eclipse Java EE IDE(Version: Oxygen.1a Release (4.7.1a))
  • jdk1.8.0_131

先写一个最基本的两位数四则运算方法,比较简单,没有写注释:

public static double doubleCal(double a1, double a2, char operator) throws Exception {
		switch (operator) {
		case '+':
			return a1 + a2;
		case '-':
			return a1 - a2;
		case '*':
			return a1 * a2;
		case '/':
			return a1 / a2;
		default:
			break;
		}
		throw new Exception("illegal operator!");
	}

解析运算表达式的方法:

	public static String getResult(String str) throws NumberFormatException, Exception {
		
		//处理一下计算过程中出现的--情况,首位--直接去掉,中间--变为+
		str = str.startsWith("--") ? str.substring(2) : str;
		str = str.replaceAll("--", "+");
		str = str.replaceAll("\\+-", "-");
		System.out.println("新表达式:"+str);
		if (str.matches("-{0,1}[0-9]+([.][0-9]+){0,1}"))//不存在运算符了,即递归结束,这里的正则为匹配所有的正负整数及小数
			return str;
		
		/*表示每次递归计算完一步后的表达式*/
		String newExpr = null;
		// 第一步:去括号至无括号
		if (str.contains("(")) {
			/*最后一个左括号的索引值*/
			int lIndex = str.lastIndexOf("(");
			/*该左括号对应的右括号的索引*/
			int rIndex = str.indexOf(")", lIndex); 
			/*括号中的字表达式*/
			String subExpr = str.substring(lIndex + 1, rIndex);
			System.out.println("准备括号:("+subExpr+")");
			newExpr = str.substring(0, lIndex) + getResult(subExpr) //调用本身,计算括号中表达式结果
					+ str.substring(rIndex + 1);
			return getResult(newExpr);
		}
		
		// 第二步:去乘除至无乘除
		if (str.contains("*") || str.contains("/")) {
			/*该正则表示匹配一个乘除运算,如1.2*3  1.2/3  1.2*-2 等*/
			Pattern p = Pattern.compile("[0-9]+([.][0-9]+){0,1}[*/]-{0,1}[0-9]+([.][0-9]+){0,1}");
			Matcher m = p.matcher(str);
			if (m.find()) {
				/*第一个乘除表达式*/
				String temp = m.group();
				System.out.println("计算乘除:"+temp);
				String[] a = temp.split("[*/]");
				newExpr = str.substring(0, m.start())
						+ doubleCal(Double.valueOf(a[0]), Double.valueOf(a[1]), temp.charAt(a[0].length()))
						+ str.substring(m.end());
			}
			return getResult(newExpr);
		}

		// 第三步:去加减至无加减
		if (str.contains("+") || str.contains("-")) {
			/*该正则表示匹配一个乘除运算,如1.2+3  1.2-3  1.2--2  1.2+-2等*/
			Pattern p = Pattern.compile("-{0,1}[0-9]+([.][0-9]+){0,1}[+-][0-9]+([.][0-9]+){0,1}");
			Matcher m = p.matcher(str);
			if (m.find()) {
				/*第一个加减表达式*/
				String temp = m.group();
				System.out.println("计算加减:"+temp);
				String[] a = temp.split("\\b[+-]", 2);
				newExpr = str.substring(0, m.start())
						+ doubleCal(Double.valueOf(a[0]), Double.valueOf(a[1]), temp.charAt(a[0].length()))
						+ str.substring(m.end());
			}
			return getResult(newExpr);
		}
		
		throw new Exception("Calculation error");
	}

主方法:

public static void main(String[] args) throws Exception {
		String str = "-3.5*(4.5-(4+(-1-1/2)))";
		System.out.println("开始计算表达式:"+str);
		System.out.println("结果为:"+getResult(str));
	}

再来个简略版的

public class test {
	static boolean isNumber(String str) {//判断表达式是不是只有一个数字
		for(int i=0;i

###四、运行结果
(算法)java完成解析数学算式(计算器)一 —— 递归、正则直接遍历字符串解析_第1张图片

五、分析

这种方法以我们平时计算的思路入手,思路较为清晰,代码简略,但直接遍历拼接字符串,代码并不好读,多次递归效率也必然较低。引入第二种思路,采用java的容器进一步优化算法及代码。

你可能感兴趣的:(数据结构与基本算法)