`
苍山洱海
  • 浏览: 5048 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

数学表达式判断以及计算

阅读更多
最近一个题目需要自己计算一个字符串数学表达式的值, 所以大体研究了一下. 自己使用java实现

功能有:

1, 支持有小数点的计算

2, 支持带负号的计算

3, 支持带括号的计算

4, 支持参数计算



代码如下:
package on0911;

import java.util.Stack;

/**
 * 计算简单数学表达式的值
 * @author Administrator
 *
 */
public class Expression {

	private Stack<Double> data = new Stack<Double>();
	private Stack<Operator> operatorStack = new Stack<Operator>();
	private String exp;
	enum Op{
		JIA('+'), JIAN('-'), CHENG('*'), CHU('/');
		private char value;
		Op(char value) {
			this.value = value;
		}
		
		public char getValue() {
			return value;
		}
	}
	
	public Expression(String exp) {
		this.exp = exp.replace(" ", "");
	}
	
	
	public static void main(String[] args) {
		String expression = "-30 + 36* 2 / 4 -  1 * - 0.4   ";
		System.out.println("表达式结果是:" + new Expression(expression).doC());
	}
	
	/**
	 * 计算表达式的值
	 * @return
	 */
	public double doC() {
		inStack();
		
		/*当符号栈不为空的时候进行计算*/
		while (operatorStack.size() > 0) {
			Double re = ontStep(data, operatorStack);
			data.push(re);
		}
		
		return data.pop();//返回最后结果
	}
	
	/**
	 * 扫描表达式, 根据条件将表达式的内容进行简单计算, 然后入栈
	 */
	public void inStack() {
		if (exp.endsWith("+") || exp.endsWith("-") || exp.endsWith("*") || exp.endsWith("/")) {
			throw new RuntimeException("表达式有误!不能以运算符结尾");
		}
		
		/*循环所有字符, 判断后进行操作*/
		for (int i = 0; i < exp.length();) {
			char c = exp.charAt(i++);//取得第一个字符
			
			/*在是数字值的情况下, 或者是负号的情况下, 继续搜索后续的字符*/
			if ((c <= '9' && c >= '0') || c == '.' || (i == 1 && c == '-') 
					|| (i > 1 && isOperator(exp.charAt(i - 2)))) {
				String temp = c + "";
				
				/*所有后续字符, 组成规定的数值*/
				for (; i < exp.length();) {
					char c2 = exp.charAt(i++);
					if ((c2 <= '9' && c2 >= '0') || c2 == '.') {
						temp += c2;
					} else {
						break;//判断跳出条件时, 漏过一个字符, 这是因为最后一个字符应该是数字, 所以如果不是数字就不管他
					}
				}
				
				/*如果不是最后一个数值的话, 游标前移一位, 重新读取刚才漏过的字符*/
				if (i != exp.length()) {
					i--;
				}
				Double num = Double.parseDouble(temp);
				data.push(num);//将数据压入数据栈
			} else {
				if (isOperator(c)){
					Operator op = new Operator(c);
					if (operatorStack.size() == 0) {
						operatorStack.push(op);//运算符栈在空的时候直接入栈
					} else {
						Operator stackPop = operatorStack.pop();
						
						//比较运算符栈栈顶运算符和当前运算符的优先级
						//1, 如果大于栈顶运算符的优先级, 就直接入栈.
						//2, 小于或者等于的话, 就先计算数据栈和运算符栈的一次, 然后将结果压入数据栈. 
						//  然后将当前运算符压入运算符栈
						if (op.getPriority() > stackPop.getPriority()) {
							operatorStack.push(stackPop);
							operatorStack.push(op);
						} else {
							operatorStack.push(stackPop);
							Double re = ontStep(data, operatorStack);//计算一次
							data.push(re);//压结果入栈
							operatorStack.push(op);//当前运算符入栈
						}
					}
				} else {
					throw new RuntimeException(c + "符号错误");
				}
			}
		}
	}
	
	private boolean isOperator(char c) {
		if (Op.JIA.getValue() == c || Op.JIAN.getValue() == c || Op.CHENG.getValue() == c || Op.CHU.getValue() == c) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * 将数据栈的数据提取两个和运算符栈的一个运算符进行计算, 且返回结果
	 * @param data2
	 * @param operatorStack2
	 * @return
	 */
	private Double ontStep(Stack<Double> data2, Stack<Operator> operatorStack2) {
		Double re = 0d;
		Double next = data2.pop();
		Double pre = data2.pop();
		Operator o = operatorStack.pop();
		re = cal(pre, o, next);//计算数据
		return re;
	}
	
	
	/**
	 * 计算得到值
	 * @param pre
	 * @param o
	 * @param next
	 * @return
	 */
	private Double cal(Double pre, Operator o, Double next) {
		if (o == null) {
			throw new RuntimeException("空操作符");
		}
		
		char cc = o.getOp();
		if (cc == Op.JIA.getValue()) {
			return new Double(pre + next);
		}
		
		if (cc == Op.JIAN.getValue()) {
			return new Double(pre - next);
		}
		
		if (cc == Op.CHENG.getValue()) {
			return new Double(pre * next);
		}
		
		if (cc == Op.CHU.getValue()) {
			return new Double(pre / next);
		}
		
		throw new RuntimeException("错误的运算符!");

	}


	/**
	 * 自定义的操作符类
	 * @author Administrator
	 *
	 */
	class Operator {
		char op;
		int priority;
		
		public Operator(char op) {
			this.op = op;
			switch (op) {
			case '+': priority = 5;break;
			case '-': priority = 5;break;
			case '*': priority = 6;break;
			case '/': priority = 6;break;
			default: throw new RuntimeException("错误的操作符");
			}
		}

		public char getOp() {
			return op;
		}

		public void setOp(char op) {
			this.op = op;
		}

		public int getPriority() {
			return priority;
		}

		public void setPriority(int priority) {
			this.priority = priority;
		}
		
		
	}
	
}


package on0911;

/**
 * 计算带括号的复杂表达式的值
 * @author Administrator
 *
 */
public class ComplexExpression {
	
	/**
	 * 计算给定字符串的表达式值
	 * @param str
	 * @return
	 */
	public double doD(String str) {
		String exp = str.replace(" ", "");//替换空字符
		int flag = 0;//标志括号位
		StringBuilder exp2 = new StringBuilder();//储存去除括号后的表达式
		
		/*扫描给定表达式字符串, 进行判断然后响应操作*/
		for (int i = 0; i < exp.length();) {
			char c = exp.charAt(i++);
			
			//碰到时左括号的时候, 标志位自加, 然后将此括号内的字符串进行计算得到数值后放到exp2中
			if (c == '(') {
				flag++;
				StringBuilder sb = new StringBuilder();//此括号内的字符串
				for (; i < exp.length();) {
					char c2 = exp.charAt(i++);
					sb.append(c2 + "");//添加字符
					//左括号自加, 右括号自减
					if (c2 == '(') {
						flag++;
					} else if (c2 == ')') {
						flag--;
					}
					
					/*碰到右括号时, 如果标志位确认是当前左括号的互补括号, 就进行递归计算此字符串的值*/
					if (c2 == ')' && flag == 0) {
						String temp = sb.substring(0, sb.length() - 1);
						temp = getValue(temp);//递归计算括号内的值
						exp2.append(temp);//将值添加到exp2字符串中
						break;
					}
				}
			} else {
				exp2.append(c);
			}
		}
		
		//System.out.println(exp2.toString());
		return new Expression(exp2.toString()).doC();//返回计算exp2值的数值
	}

	/**
	 * 递归计算给定字符串的值
	 * @param temp
	 * @return
	 */
	private String getValue(String temp) {
		temp = temp.replace(" ", "");
		if (!temp.contains("(")) {
			return new Expression(temp).doC() + "";//当不含有括号的时候,直接返回计算值
		}
		
		return doD(temp) + "";//有括号的时候就返回计算括号内得到的值
	}
	
	public static void main(String[] args) {
		//String str = "3 *- (1 - 2 / 4) + ( 1 + (2 - 3)) + 2";
		//System.out.println("答案是:" + new ComplexExpression().getValue(str));
		varTest();
	}
	
	public static void varTest() {
		int A = 2, B = 34;
		String str = "3 *- (A - 2 / 4) + ( 1 + (2 - B)) + 2";
		str = str.replace("A", A + "");
		str = str.replace("B", B + "");
		
		System.out.println("答案是:" + new ComplexExpression().getValue(str));
	}
}

分享到:
评论
1 楼 tangzililiang 2010-03-22  
表达式格式的检查严重不足!!!
Global site tag (gtag.js) - Google Analytics