数式の判断と計算

8370 ワード

最近のテーマは文字列の数学式の値を自分で計算する必要があるので、大体研究した.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));
	}
}