import java.awt.Color;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class CalculatorFrame extends JFrame implements ActionListener // throws NullPointerException
{
	private static final long serialVersionUID = -2769614160013503222L;
	private JTextField tf = new JTextField(); // 创建文本框tf
	private Calculator calculator = new Calculator();

	public CalculatorFrame() throws HeadlessException {
		JPanel pan = new JPanel(); // 创建一个面板对象pan
		GridLayout grid = new GridLayout(5, 4); // 创建6行4列的页面布局
		// 对面板pan和文本框tf的一些设置
		pan.setLayout(grid);
		tf.setBounds(35, 15, 250, 25);
		pan.setBounds(35, 50, 250, 150);
		tf.setBackground(Color.CYAN);
		tf.setHorizontalAlignment(JTextField.RIGHT);

		String[][] btnArray = { { "1", "2", "3", "+" }, { "4", "5", "6", "-" }, { "7", "8", "9", "*" },
				{ "0", ".", "", "/" }, { "AC", "%", "←", "=" } };
		for (int i = 0; i < btnArray.length; i++) {
			for (int j = 0; j < btnArray[i].length; j++) {
				JButton btn = new JButton(btnArray[i][j]);
				// 编辑bp的监听事件源为本窗口
				btn.addActionListener(this);
				// 将按钮添加到面板pan中
				pan.add(btn);
			}
		}

		// 添加面板pan和文本框tf到窗口frm
		this.add(tf);
		this.add(pan);
		// 关于窗口frm的一些设置
		this.setTitle("计算器");
		this.setLayout(null); // 取消窗口的布局管理
		this.setSize(325, 250);
		this.setResizable(false); // 设置窗口的大小为不可变
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);

	}

	public static void main(String[] args) throws NullPointerException {
		new CalculatorFrame();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		JButton but = (JButton) e.getSource();
		String text = but.getText();
		String content = tf.getText();
		if ("←".equals(text)) {
			if (content != null && content.length() >= 1) {
				tf.setText(content.substring(0, content.length() - 1));
			}
		} else if ("=".equals(text)) {
			Double value = calculator.calculator(content);
			if (value != null)
				tf.setText(String.valueOf(value));
		} else if ("AC".equals(text)) {
			tf.setText("");
		} else {
			tf.setText(content + text);
		}
	}

	private class Calculator {
		// 定义操作符的优先级别
		private Map<String, Integer> operatorPriority = new HashMap<String, Integer>();

		public Calculator() {
			super();
			// 设置操作符优先级,数越大优先级越高
			operatorPriority.put("+", 1);
			operatorPriority.put("-", 1);
			operatorPriority.put("*", 2);
			operatorPriority.put("/", 2);
			operatorPriority.put("%", 2);
			operatorPriority.put("(", 3);
			operatorPriority.put(")", 3);
		}

		/**
		 * 计算算术表达式
		 * 
		 * @param str
		 *            算术表达式
		 * @return 结果
		 */
		public Double calculator(String str)// 科学计算
		{
			if (str == null || "".equals(str))
				return null;

			List<String> numList = getStringList(str);// 拆分操作符与操作数
			numList = getPostOrder(numList); // 中缀变后缀
			Stack<Double> stack = new Stack<Double>();// 结果栈
			for (int i = 0; i < numList.size(); i++) {
				String temp = numList.get(i);
				if (Character.isDigit(temp.charAt(0))) {// 如果是数字
					stack.push(Double.valueOf(temp));
				} else {
					Double back = stack.pop();
					Double front = stack.pop();
					Double res = 0d;
					switch (temp.charAt(0)) {
					case '+':
						res = front + back;
						break;
					case '-':
						res = front - back;
						break;
					case '*':
						res = front * back;
						break;
					case '/':
						res = front / back;
						break;
					case '%':
						res = front % back;
						break;
					}
					stack.push(res);
				}
			}
			return stack.pop();
		}

		/**
		 * 将中缀表达式转换到后缀表达式
		 * 
		 * <pre>
		 * 	平时所用的标准四则运算表达式,即"9+(3-1)*3+10/2"叫做中缀表达式。因为所有的运算符号都在两数字的中间,现在我们的问题就是中缀到后缀的转化;
		 *  中缀表达式“9+(3-1)*3+10/2”转化为后缀表达式“9 3 1-3*+ 10 2/+”
		 *  
		 *  规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;
		 *  	若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,
		 *  	一直到最终输出后缀表达式为止。
		 * </pre>
		 * 
		 * 参见链接:<a
		 * href="http://www.nowamagic.net/librarys/veda/detail/2307">http://www.nowamagic.net/librarys/veda/detail
		 * /2307</a>
		 * 
		 * @param postOrder
		 * @return
		 */
		public List<String> getPostOrder(List<String> inOrderList) {

			ArrayList<String> result = new ArrayList<String>();// 结果列表
			Stack<String> stack = new Stack<String>();// 操作符栈
			for (int i = 0; i < inOrderList.size(); i++) {
				String str = inOrderList.get(i);
				// 判断当前是不是数字
				if (Character.isDigit(str.charAt(0))) {
					result.add(inOrderList.get(i));// 是数字直接添加
				} else {
					// 如果是操作符
					switch (str.charAt(0)) {
					case '(':
						stack.push(str);// 往操作符栈中添加
						break;
					case ')':
						while (!stack.peek().equals("(")) {
							result.add(stack.pop());
						}
						stack.pop();
						break;
					default:
						// 其他操作符
						while (!stack.isEmpty() && compare(stack.peek(), str) >= 0) {
							result.add(stack.pop());
						}
						stack.push(inOrderList.get(i));
						break;
					}
				}
			}
			while (!stack.isEmpty()) {
				result.add(stack.pop());
			}
			return result;
		}

		/**
		 * 将字符串转换成由操作符和操作数组成的字符串数组
		 * 
		 * @param str
		 *            算数运算表达式
		 * @return
		 */
		private List<String> getStringList(String str) {
			// 数字临时变量
			StringBuffer sb = new StringBuffer();
			// 将字符串转成操作数与操作符数组
			List<String> numList = new ArrayList<String>();
			for (char c : str.toCharArray()) {
				// 空白字符 继续循环
				if (Character.isWhitespace(c)) {
					continue;
				}
				// 如果是数字或者点号
				if (Character.isDigit(c) || '.' == c) {
					sb.append(c);
				} else {
					numList.add(sb.toString());// 将数字添加到列表中
					sb.setLength(0);// 清空数字临时变量
					numList.add(String.valueOf(c));// 将操作符添加到列表中
				}
			}
			numList.add(sb.toString());
			return numList;
		}

		/**
		 * 比较运算符等级 ,
		 * 
		 * <pre>
		 *  如果operator1 > operator2 返回 正数, 
		 *  如果operator1 < operator2 返回 负数, 
		 *  如果operator1 = operator2 返回 零
		 * </pre>
		 * 
		 * @param operator1
		 *            操作符
		 * @param operator2
		 *            操作符
		 * @return
		 */

		public int compare(String operator1, String operator2) {
			return operatorPriority.get(operator1) - operatorPriority.get(operator2);
		}
	}

}


Java简单计算器_操作符

Java简单计算器_java_02