Java-エクスプレッション計算機


Java-エクスプレッション計算機
JavaScriptでは、式文字列を実行するためにeval()という関数があることを知っています.とても便利です.しかしC++、Javaでは、こんなに便利なツールは使われていません.
式を評価するには、次の2つのステップがあります.
①接頭辞式接頭辞式を求める
②接頭辞式演算評価
この2つのステップは、2つのスタック、オペレータスタック、オペランドスタックをそれぞれ利用する.
具体的な説明は『
MFCは加減乗除、括弧、乗方の計算機を実現する
プログラムソース:
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.Stack;

public class Work5 {
	//     
	private static Stack<Double> Operands;
	//     
	private static Stack<Character> Operators;
	//      
	private static final Set<Character> C_OperatorSet = new HashSet<Character>() {
		/**
		* 
		*/
		private static final long serialVersionUID = 1L;

		{
			add('+');
			add('-');
			add('*');
			add('/');
			add('^');
			add('(');
			add(')');
		}
	};

	private static int getOperatorPriority(char ch) {
		if (ch == '+' || ch == '-')
			return 0;
		else if (ch == '*' || ch == '/')
			return 1;
		else if (ch == '^')
			return 3;
		else
			return -1;
	}

	private static String infixToSuffix(String expression) {
		Operators = new Stack<>();
		Operators.clear();
		StringBuilder sBuilder = new StringBuilder();
		for (int i = 0; i < expression.length(); i++) {
			char ch = expression.charAt(i);
			if (ch == ' ')
				continue;
			if (C_OperatorSet.contains(ch)) {
				if (Operators.empty()) {
					if (ch == ')') {
						System.out.println("     ");
						return sBuilder.toString();
					}
					Operators.push(ch);
				} else if (ch == '(') {
					Operators.push(ch);
				} else if (ch == ')') {
					char top;
					while ((top = Operators.peek()) != '(') {
						if (Operators.empty()) {
							System.out.println("     ");
							return sBuilder.toString();
						}
						sBuilder.append(top);
						Operators.pop();
					}
					Operators.pop();
				} else {
					char top = Operators.peek();
					if (getOperatorPriority(ch) <= getOperatorPriority(top)) {
						while (!Operators.empty()
								&& getOperatorPriority(ch) <= getOperatorPriority(top = Operators.peek())) {
							sBuilder.append(top);
							Operators.pop();
						}
					}
					Operators.push(ch);
				}
			} else {
				sBuilder.append("[" + ch);
				while (i + 1 < expression.length()
						&& (((ch = expression.charAt(i + 1)) == '.') || (ch >= '0' && ch <= '9'))) {
					sBuilder.append(ch);
					++i;
				}
				sBuilder.append(']');
			}
		}
		while (!Operators.empty()) {
			sBuilder.append(Operators.peek());
			Operators.pop();
		}
		return sBuilder.toString();
	}

	public static double evalExp(String expression) {
		Operands = new Stack<>();
		Operands.clear();
		double ret = 0;
		String suffix = infixToSuffix(expression);
		System.out.println("suffix: " + suffix);
		for (int i = 0; i < suffix.length(); i++) {
			if (suffix.charAt(i) == '[') {
				i++;
				int beginIndex = i, endIndex = i;
				while (']' != suffix.charAt(i)) {
					i++;
					endIndex++;
				}
				Operands.push(Double.valueOf(suffix.substring(beginIndex, endIndex)));
			} else {
				double left, right, res = 0;
				right = Operands.peek();
				Operands.pop();
				left = Operands.peek();
				Operands.pop();
				switch (suffix.charAt(i)) {
				case '+':
					res = left + right;
					break;
				case '-':
					res = left - right;
					break;
				case '*':
					res = left * right;
					break;
				case '/':
					res = left / right;
					break;
				case '^':
					res = Math.pow(left, right);
					break;
				}
				Operands.push(res);
			}
		}
		ret = Operands.peek();
		Operands.pop();
		return ret;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner input = new Scanner(System.in);
		System.out.println("      +-*/^()    ,       ");
		String expression = input.nextLine();
		System.out.println(expression + " =" + evalExp(expression));
		input.close();
	}

}