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); } } }