package Caculator; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.Frame; import java.awt.GridLayout; import java.awt.Panel; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.math.BigDecimal; import java.math.MathContext; import javax.swing.JFrame; import com.sun.glass.events.WindowEvent; public class MyCalculator { public static void main(String[] args) { new MyCalculator().launch(); } public boolean result=false;//输入#之后result变为真,此时可以计算结果了,用于判断能否进行计算。 public boolean end=false;//前面有内容的时候才将其变为true,且输入#之后什么都不能输入了。 /** * 首先对这几个boolean变量进行具体阐述:rusult只有在#(结束符)输入之后才会赋为true,也就是说只有输入#之后才能输入==; * end用于#(结束符)能否进行输入,#前必须为正确的式子,故#的前一位只能是数字或者右括号。 * * 分为以下几种:数字,算数符(+ - * /),左括号,右括号,点,清零符 * 数字任何时候均可进行输入 * judge1用于运算符的判断,运算符之前只能有数字,括号 * judge2用于点的判断。 * judgeleft用于左括号的判定,另外只有在输入左括号之后才能输入右括号,另外输完左括号之后还能再输,可以连续输入两个左括号 * judgeleftright 用于右括号的判定,另外输完右括号之后还能再输,可以连续输入两个右括号 * 其中还有一些情况没有完全避免 * */ public boolean judge1=false; public boolean judge2=true; public boolean judgeleft=true; public boolean judgeleftright=false; public void launch() { TextField tf=new TextField(30); tf.setSize(300, 100); tf.setBackground(Color.WHITE); tf.setEditable(true); JFrame interface1=new JFrame(); interface1.setTitle("按#=得结果"); interface1. setLayout(new BorderLayout());//创建BorderLayout布局(几行几列) interface1.add(tf,BorderLayout.NORTH); Panel p=new Panel(new GridLayout(5,4,5,5));//将面板设置成5行四列 for(int i=0;i<10;i++) { Button bn=new Button(""+i); bn.setActionCommand("数字");//数字为一类 p.add(bn); bn.addActionListener(new ActionEventDemo(interface1,tf)); } Button D=new Button("."); D.setActionCommand("点"); p.add(D); D.addActionListener(new ActionEventDemo(interface1,tf));//点为一类 Button add=new Button("+"); add.setActionCommand("算数符"); p.add(add); add.addActionListener(new ActionEventDemo(interface1,tf)); Button sub=new Button("-"); sub.setActionCommand("算数符"); p.add(sub); sub.addActionListener(new ActionEventDemo(interface1,tf)); Button mult=new Button("*"); mult.setActionCommand("算数符"); p.add(mult); mult.addActionListener(new ActionEventDemo(interface1,tf)); Button div=new Button("/"); div.setActionCommand("算数符"); p.add(div); div.addActionListener(new ActionEventDemo(interface1,tf));//运算符为一类 Button left=new Button("("); left.setActionCommand("左括号"); p.add(left); left.addActionListener(new ActionEventDemo(interface1,tf)); Button right=new Button(")"); right.setActionCommand("右括号"); p.add(right); right.addActionListener(new ActionEventDemo(interface1,tf));//括号为一类 Button end=new Button("#"); end.setActionCommand("结束符"); p.add(end); end.addActionListener(new ActionEventDemo(interface1,tf));//结束符 Button result=new Button("=="); result.setActionCommand("结果符"); p.add(result); result.addActionListener(new ActionEventDemo(interface1,tf));//按完结束符才能按结果符 Button zero =new Button("清零"); zero.setActionCommand("清零符"); p.add(zero); zero.addActionListener(new ActionEventDemo(interface1,tf)); interface1.add(p,BorderLayout.CENTER); interface1.setBounds(300,300,400,400); interface1.setBackground(Color.black); interface1. setVisible(true); interface1.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(-1); } } ); } class ActionEventDemo implements ActionListener { JFrame interface1=new JFrame(); TextField tf=new TextField(); ActionEventDemo(JFrame interface1,TextField tf){ this.interface1=interface1; this.tf=tf; } public void actionPerformed(ActionEvent e) { String strAc=e.getActionCommand();//*得到按钮实际命令。 Button bn=(Button)e.getSource(); String strLb=bn.getLabel();//得到按钮标签 if(strAc.equals("数字")) { tf.setText(tf.getText()+strLb); judge1=true;//输入数字之后就可以输算数符+ - * /了 end=true;//可以上输入结束符了,#符号之前只能是数字或者右括号 judgeleft=true; } else if(strAc.equals("算数符")&&judge1) {//运算符是一种 tf.setText(tf.getText()+strLb); judge1=false; judge2=true; end=false; judgeleft=true; } else if(strAc.equals("左括号")&&judgeleft) {//左括号是一种 tf.setText(tf.getText()+strLb); judgeleftright=true;//可以输入右括号了 end=false;//#符号之前只能是数字或者右括号 } else if(strAc.equals("右括号")&&judgeleftright) {//右括号是一种 tf.setText(tf.getText()+strLb); //judgeleftright=false; judgeleft=true; end=true; } else if(strAc.equals("点")&&judge2) {//点是一种 tf.setText(tf.getText()+strLb); judge2=false; judgeleft=false; end=false; } else if(strAc.equals("清零符")) { tf.setText(""); //boolean变量全部赋成初值 result=false;//输入#之后result变为真,此时可以计算结果了,用于判断能否进行计算。 end=false;//前面有内容的时候才将其变为true,且输入#之后什么都不能输入了。 judge1=false; judge2=true; judgeleft=true; judgeleftright=false; } else if(strAc.equals("结束符")&&end) { tf.setText(tf.getText()+strLb); result=true; //什么都没法输入了,表示已经结束运算 end=false; judge1=false; judge2=false; judgeleft=false; judgeleftright=false; } else if(strAc.equals("结果符")&&result) { String string=tf.getText();//得到结果符,获得TextField标签上内容字符串 MyCaculate caculate=new MyCaculate ();//形成计算的类的对象 double end1=caculate.caculate(tf.getText());//通过caculate方法得到计算结果end1 BigDecimal bg = new BigDecimal(end1); double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); tf.setText(String.valueOf(f1)+""); } } } } package Caculator; import java.util.Stack; /** * 利用栈,进行四则运算的类 * 用两个栈来实现算符优先,一个栈用来保存需要计算的数据numStack,一个用来保存计算优先符priStack * * 基本算法实现思路为:用当前取得的运算符与priStack栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶; * 若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算; * 若小于,则同理,取出栈顶元素运算,将结果入操作数栈。各个优先级‘(‘ > ‘*‘ = ‘/‘ > ‘+‘ = ‘-‘ > ‘)‘ * */ public class MyCaculate { Stack<Double> numStack = new Stack<Double>();;// 操作数栈 Stack<Character> priStack = new Stack<Character>();// 操作符栈 //放在最前面,在方法中用不了 public double caculate(String numStr1) { String numStr=numStr1.substring(0, numStr1.length()-1);//由于设置原因GUI界面传入的字符串最后一个字符为#,把它去掉,不去掉也行,那就把#作为结束符 if (numStr.length() > 1 && !"=".equals(numStr.charAt(numStr.length() - 1) )) { numStr += "="; //=作为结束符 } StringBuffer temp=new StringBuffer();//为提高效率,临时存放字符 int i=0; for(i=0;i<numStr.length();i++) {//大循环 char ch=numStr.charAt(i); if(isNumber(ch)) temp.append(ch); else { //转换成String类型 if(!"".equals(temp.toString())) {//它是符号了说明符号前面的数字切割完毕 double num=Double.parseDouble(temp.toString()); numStack.push(num); temp.delete(0, temp.length());//temp存放临时结果,放入栈中. } // 用当前取得的运算符与栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算; // 若小于,则同理,取出栈顶元素运算,将结果入操作数栈。 // 判断当前运算符与栈顶元素优先级,取出元素,进行计算(因为优先级可能小于栈顶元素,还小于第二个元素等等,需要用循环判断) while(!compare(ch)&&!priStack.empty()) {//不如栈顶元素优先级高,那么我们将栈顶运算符取出,进行运算即可。 double b=numStack.pop(); double a=numStack.pop(); double c; switch((char)priStack.pop()) { case ‘+‘:c=a+b; numStack.push(c); break; case ‘-‘:c=a-b; numStack.push(c);break; case ‘*‘:c=a*b;numStack.push(c);break; case ‘/‘:c=a/b;numStack.push(c);break; } } if(ch!=‘=‘) {priStack.push(new Character(ch)); if(ch==‘)‘) {// 当栈顶为‘(‘,而当前元素为‘)‘时,则是括号内以算完,去掉括号 priStack.pop(); priStack.pop(); } } } } return numStack.pop(); } private boolean isNumber(char num) { if (num >= ‘0‘ && num <= ‘9‘||num==‘.‘) return true; else return false;//有了这个方法就不用判断他是否是数字还是符号了,如果是.也把它当作数字来看待 } /** * 比较当前操作符与栈顶元素操作符优先级,如果比栈顶元素优先级高,即最后算,则返回true,否则返回false * * str 需要进行比较的字符 * 比较结果 true代表比栈顶元素优先级高,false代表比栈顶元素优先级低 ,true表示后算 */ public boolean compare(char str) { if (priStack.empty()) { // 当为空时,显然 当前优先级最低,返回高 return true; } char last = (char) priStack.lastElement(); // 如果栈顶为‘(‘显然,优先级最低,‘)‘不可能为栈顶。 if (last == ‘(‘) { //‘(‘为栈顶无法放入其他符号,直到遇到右括号出栈,入栈 return true; } switch (str) { // ‘+-‘为最低,一直返回false,先算,出栈 case ‘+‘: return false; case ‘-‘: return false; case ‘(‘: // ‘(‘优先级最高,显然返回true,最后算,入栈 return true; case ‘=‘: return false;// 结束符 ,全部出栈 case ‘)‘: // ‘)‘优先级最低,前面必有左括号,出栈 return false; case ‘*‘: { if (last == ‘+‘ || last == ‘-‘) //入栈 return true; else return false; //栈顶元素出栈 } case ‘/‘: { if (last == ‘+‘ || last == ‘-‘) return true; //入栈 else return false; //栈顶元素出栈 } } return true; } //public static void main(String []args) { // MyCaculate operate = new MyCaculate(); // double t = operate.caculate("((9.8-3.5)/(25.1-25.3)+7)*4#"); // System.out.println(t); // }//用于测试数据 }
原文:https://www.cnblogs.com/lyd66-/p/12127686.html