java实现科学计算器的全过程与代码
目录
- 介绍
- 实现思路
- 实现过程和代码
- 1.界面设计
- 2.栈,中缀转后缀
- 3.判断错误
- 4.计算后缀表达式
- 5.事件监听器
- 完整代码
- 总结
介绍
本次设计的是一个有33个按钮的科学计算器。可以进行加,减,乘,除,开根号,阶乘,次方,百分号,对数,三角函数的计算。
实现思路
通过点击按钮可以得到一个算术表达式,并且它是一个字符串类型,然后需要做的就是把这个字符串转化为计算机可计算的形式。这里就需要用到中缀表达式转化为后缀表达式。转化完之后通过栈来一步步的进行输出和计算,最后输出结果。
实现过程和代码
1.界面设计
设计效果如图所示:
由图片可知,总共设计了两个文本框和33个按钮(这里的布局是我直接用setBounds()方法设计的。因为如果用布局管理器的话要达到自己想要的效果不太方便)。
在设计时要注意的是:
1.不能把按钮和文本框直接加入JFrame中,因为如果JFrame.setLayout(null)的话,面板上就会出问题,什么都看不到或者其他情况。因此建议创建一个JPanel,把JPanel的setLayout()设置为空。把按钮和文本框加入到JPanel中,再把JPanel加入到JFrame中。就不会出问题了。JFrame的布局管理器默认为流式布局,位置是中心区域。
2.设计完长度后,宽度一般要再加15个像素点,高度要再加35个像素点.要不然会有一部分按钮看不到。如我本意要设计的面板宽为600,高为400,则实际上是
jFrame.setSize(614, 437);
下面就是我设计的界面的代码:
private JFrame jFrame = new JFrame("计算器"); //设置字体,是否加粗,大小 private FontUIResource f = new FontUIResource("隶书", 1, 20); private FontUIResource f1 = new FontUIResource("楷书", 0, 35); private JPanel jPanel = new JPanel(); private int buttonx = 100; private int buttony = 50; private int yy = 50; //两个文本框 private JTextField jTextField1 = new JTextField("0", 30); private JTextField jTextField2 = new JTextField("输入要求在main()中", 30); private String str = ""; private String temp = ""; private int indexYN = 0; private String[] strings = { "(", ")", "1/x", "x^2", "x^3", "x^y", "x!", "√", "e", "ln", "log", "%", "sin", "cos", "tan", "π", "+", "=", "7", "8", "9", "0", "-", "4", "5", "6", ".", "*", "1", "2", "3", "c", "÷" }; //33个按钮 private JButton[] buttons = new JButton[33]; public void loAsi(){ int tep = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 6; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } int lo = 0; for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j++) { buttons[lo++].setBounds(buttonx * j, yy * (2 + i), buttonx, buttony); } } for (int i = 0; i < 5; i++) { buttons[lo++].setBounds(buttonx * i, yy * 4, buttonx, buttony); } buttons[lo++].setBounds(buttonx * 5, yy * 4, buttonx, buttony * 4); for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[lo++].setBounds(buttonx * j, yy * (5 + i), buttonx, buttony); } } jTextField1.setBounds(0, yy, 600, yy);//设置位置 jTextField1.setFont(f1);设置字体 jTextField1.setHorizontalAlignment(JLabel.RIGHT);//文本靠右 jTextField1.setEditable(false);//不可修改 jTextField1.setBackground(Color.WHITE);//颜色为白色 jTextField2.setBounds(0, 0, 600, yy); jTextField2.setFont(f1); jTextField2.setHorizontalAlignment(JLabel.RIGHT); jTextField2.setEditable(false); jTextField2.setBackground(Color.WHITE); } public void initButton(){//把按钮添加到jPanel中 this.loAsi(); jPanel.add(jTextField1); jPanel.add(jTextField2); for (int i = 0; i < buttons.length; i++) { jPanel.add(buttons[i]); } jPanel.setLayout(null);//布局管理器为空,自定义设计 } public void init(){ this.initButton(); this.buttonLister(); jFrame.add(jPanel);//把jPanel添加到jFrame中 jFrame.setSize(614, 437);//jFrame的长宽 jFrame.setResizable(false);//大小不可修改 jFrame.setLocationRelativeTo(null);//位置为显示器的正中间 //窗口监听器,点右上角的关闭就关闭窗口 //可以不写,应为JFrame默认的就可以关闭,不需要写事件监听器。如果是Frame的话需要写。 jFrame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); jFrame.setVisible(true);//设置面板可见 }
2.栈,中缀转后缀
我总共设计了12种运算符:(+, -, * , /, ^, !, g, l, o, s, c, t)分别是加,减,乘,除,次方,阶乘,开根号,,对数ln, 对数log2, sin, cos, tan
e是Math.E, p是Math.PI, %是直接乘以0.001
把中缀表达式转换为后缀表达式。例如:
中缀表达式:1+2*3+(l2+3)/2
后缀表达式为:123*+23+2/+
后缀表达式的运算步骤是:
1.16+23+2/+
2.723+2/+
3.752/+
4.7 2.5+
5.9.5
代码如下:
private List<String> zhongZhui(String str) {//把输入的字符串转换成中缀表达式。存入list中 int index = 0; List<String> list = new ArrayList<>(); do{ char ch = str.charAt(index); if("+-*/^!logsct()".indexOf(str.charAt(index)) >= 0){ //是操作符,直接添加至list中 index ++; list.add(ch+""); }else if (str.charAt(index) == 'e' || str.charAt(index) == 'p'){ index ++; list.add(ch+""); } else if("0123456789".indexOf(str.charAt(index)) >= 0){ //是数字,判断多位数的情况 String str1 = ""; while (index < str.length() && "0123456789.".indexOf(str.charAt(index)) >= 0){ str1 += str.charAt(index); index ++; } list.add(str1); } }while (index < str.length()); return list; } public List<String> houZhui(List<String> list){//中缀表达式转换称后缀表达式 Stack<String> fuZhan = new Stack<>(); List<String> list2 = new ArrayList<>(); if (!list.isEmpty()) { for (int i = 0; i < list.size(); i++) { if (isNumber(list.get(i))){ list2.add(list.get(i)); } else if (list.get(i).charAt(0) == '('){ fuZhan.push(list.get(i)); } else if (isOperator(list.get(i)) && list.get(i).charAt(0) != '('){ if (fuZhan.isEmpty()){ fuZhan.push(list.get(i)); } else {//符栈不为空 if (list.get(i).charAt(0) != ')'){ if (adv(fuZhan.peek()) <= adv(list.get(i))){ //入栈 fuZhan.push(list.get(i)); } else {//出栈 while (!fuZhan.isEmpty() && !"(".equals(fuZhan.peek())){ if(adv(list.get(i)) <= adv(fuZhan.peek())){ list2.add(fuZhan.pop()); } } if (fuZhan.isEmpty() || fuZhan.peek().charAt(0) == '('){ fuZhan.push(list.get(i)); } } } else if (list.get(i).charAt(0) == ')'){ while (fuZhan.peek().charAt(0) != '('){ list2.add(fuZhan.pop()); } fuZhan.pop(); } } } } while (!fuZhan.isEmpty()){ list2.add(fuZhan.pop()); } } else { jTextField1.setText(""); } return list2; } public static boolean isOperator(String op){//判断是否为操作符 if ("0123456789.ep".indexOf(op.charAt(0)) == -1) { return true; } else { return false; } } public static boolean isNumber(String num){//判断是否为操作数 if ("0123456789ep".indexOf(num.charAt(0)) >= 0) { return true; } else { return false; } } public static int adv(String f){//判断操作符的优先级 int result = 0; switch(f) { case "+": result = 1; break; case "-": result = 1; break; case "*": result = 2; break; case "/": result = 2; break; case "^": result = 3; break; case "!": result = 4; break; case "g": result = 4; break; case "l": result = 4; break; case "o": result = 4; break; case "s": result = 4; break; case "c": result = 4; break; case "t": result = 4; break; } return result; }
3.判断错误
下面是一些我能想到的一些输入错误和运算错误:
//当只有一位字符时,只能是“0123456789ep”中的一个
//1.第一个字符只能为"losctg(0123456789ep"中的一个
//2.“±/”后面只能是"0123456789losctg(ep"中的一个
//3.".“后面只能是“0123456789”中的一个
//4.”!"后面只能是“±/^)”中的一个
//5."losctg"后面只能是“0123456789(ep”中的一个
//6."0"的判断操作
//1.当0的上一个字符不为"0123456789."时,后一位只能是“±/.!^)”中的一个
//2.如果0的上一位为“.”,则后一位只能是“0123456789±/.^)”中的一个
//3.如果0到上一个运算符之间没有“.”的话,整数位第一个只能是“123456789”,
// 且后一位只能是“0123456789±/.!^)”中的一个。
//4.如果0到上一个运算符之间有一个“.”的话,则后一位只能是“0123456789±/.^)”中的一个
//7."123456789"后面只能是“0123456789±/.!^)”中的一个
//8."(“后面只能是“0123456789locstg()ep”中的一个
//9.”)"后面只能是“±/!^)”中的一个
//10.最后一位字符只能是“0123456789!)ep”中的一个
//12.不能有多个“.”
//13."ep"后面只能是“±*/^)”中的一个
除数不能为0
阶乘必须为自然数
ln的x必须大于0
log的x必须大于0
tan的x不能为±(π/2 + kπ)
括号是否匹配
代码如下:
public void estimate(){//判断输入是否错误 int i = 0; if (str.length() == 0){ } if (str.length() == 1){ //当只有一位字符时,只能是“0123456789ep”中的一个 if ("0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } } if (str.length() > 1){ for (i = 0; i < str.length() - 1; i++) { //1.第一个字符只能为"losctg(0123456789ep"中的一个 if ("losctg(0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //2.“+-*/”后面只能是"0123456789losctg(ep"中的一个 if ("+-*/".indexOf(str.charAt(i)) >= 0 && "0123456789losctg(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //3."."后面只能是“0123456789”中的一个 if (str.charAt(i) == '.' && "0123456789".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //4."!"后面只能是“+-*/^)”中的一个 if (str.charAt(i) == '!' && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //5."losctg"后面只能是“0123456789(ep”中的一个 if ("losctg".indexOf(str.charAt(i)) >= 0 && "0123456789(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //6."0"的判断操作 if (str.charAt(0) == '0' && str.charAt(1) == '0'){ jTextField1.setText("输入错误!"); indexYN = 1; } if (i >= 1 && str.charAt(i) == '0'){ //&& str.charAt(0) == '0' && str.charAt(1) == '0' int m = i; int n = i; int is = 0; //1.当0的上一个字符不为"0123456789."时,后一位只能是“+-*/.!^)”中的一个 if ("0123456789.".indexOf(str.charAt(m - 1)) == -1 && "+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //2.如果0的上一位为“.”,则后一位只能是“0123456789+-*/.^)”中的一个 if (str.charAt(m - 1) == '.' && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } n -= 1; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } //3.如果0到上一个运算符之间没有“.”的话,整数位第一个只能是“123456789”, // 且后一位只能是“0123456789+-*/.!^)”中的一个。 if ((is == 0 && str.charAt(n) == '0') || "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //4.如果0到上一个运算符之间有一个“.”的话,则后一位只能是“0123456789+-*/.^)”中的一个 if (is == 1 && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } if (is > 1){ jTextField1.setText("输入错误!"); indexYN = 1; } } //7."123456789"后面只能是“0123456789+-*/.!^)”中的一个 if ("123456789".indexOf(str.charAt(i)) >= 0 && "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //8."("后面只能是“0123456789locstg()ep”中的一个 if (str.charAt(i) == '(' && "0123456789locstg()ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //9.")"后面只能是“+-*/!^)”中的一个 if (str.charAt(i) == ')' && "+-*/!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //10.最后一位字符只能是“0123456789!)ep”中的一个 if ("0123456789!)ep".indexOf(str.charAt(str.length() - 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //12.不能有多个“.” if (i > 2 && str.charAt(i) == '.'){ int n = i - 1; int is = 0; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } if (is > 0){ jTextField1.setText("输入错误!"); indexYN = 1; } } //13."ep"后面只能是“+-*/^)”中的一个 if ("ep".indexOf(str.charAt(i)) >= 0 && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } } } }
4.计算后缀表达式
代码如下:
public double math(List<String> list2) {//通过后缀表达式进行计算 Stack<String> stack = new Stack<String>(); for (int i = 0; i < list2.size(); i++) { if (isNumber(list2.get(i))) { if (list2.get(i).charAt(0) == 'e'){ stack.push(String.valueOf(Math.E)); } else if (list2.get(i).charAt(0) == 'p'){ stack.push(String.valueOf(Math.PI)); } else { stack.push(list2.get(i)); } } else if (isOperator(list2.get(i))){ double res = 0; if (list2.get(i).equals("+")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 + num2; } else if (list2.get(i).equals("-")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 - num2; } else if (list2.get(i).equals("*")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 * num2; } else if (list2.get(i).equals("/")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); if (num2 != 0){ res = num1 / num2; } else { jTextField1.setText("除数不能为0"); indexYN = 1; } } else if (list2.get(i).equals("^")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = Math.pow(num1, num2); } else if (list2.get(i).equals("!")) { double num1 = Double.parseDouble(stack.pop()); if (num1 == 0 || num1 == 1){ res = 1; } else if (num1 == (int)num1 && num1 > 1){ int d = 1; for (int j = (int)num1; j >0; j--) { d *= j; } res = d; } else { jTextField1.setText("阶乘必须为自然数"); indexYN = 1; } } else if (list2.get(i).equals("g")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sqrt(num1); } else if (list2.get(i).equals("l")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1); } else { jTextField1.setText("ln的x必须大于0"); indexYN = 1; } } else if (list2.get(i).equals("o")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1) / Math.log(2); } else { jTextField1.setText("log的x必须大于0"); indexYN = 1; } } else if (list2.get(i).equals("s")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sin(num1); } else if (list2.get(i).equals("c")) { double num1 = Double.parseDouble(stack.pop()); res = Math.cos(num1); } else if (list2.get(i).equals("t")) { double num1 = Double.parseDouble(stack.pop()); if (Math.cos(num1) != 0){ res = Math.tan(num1); } else { jTextField1.setText("tan的x不能为+-(π/2 + kπ)"); indexYN = 1; } } stack.push("" + res); } } if (indexYN == 0){ if (!stack.isEmpty()){ return Double.parseDouble(stack.pop()); } else { return 0; } } else { return -999999; } } public void zhanDui(){//进行计算,并且判断括号是否匹配 String khao = ""; int leftkh = 0; int rightkh = 0; int m = 0; //判断括号是否成对 for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '('){ khao += '('; leftkh++; } if (str.charAt(i) == ')'){ khao += ')'; rightkh++; } } if (leftkh != rightkh){ jTextField1.setText("输入错误!括号不匹配"); indexYN = 1; } if ((leftkh == 0 && rightkh == 0) || ((leftkh == rightkh && leftkh > 0) && khao.charAt(0) == '(' && khao.charAt(khao.length() - 1) == ')')){ if (indexYN == 0){ List<String> list1 = zhongZhui(str); //System.out.println(list1); List<String> list2 = houZhui(list1); //System.out.println(list2); if (indexYN == 0){ if (math(list2) == -999999){ jTextField1.setText(jTextField1.getText()); } else { jTextField1.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); } } } } else { jTextField1.setText("输入错误!括号不匹配"); indexYN = 1; } }
5.事件监听器
因为设置了33个按钮,所以每个按钮都要设计事件监听器,我设置的目的是把点中的按钮的值写入到文本框中输出,并且把它代表的数值或者操作符存放到字符串中,以便于进行中缀转后缀和运算。
代码如下:
public void buttonLister(){//事件监听器 int tep = 0; buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "("); str += "("; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + ")"); str += ")"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1/"); str += "1/"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^2"); str += "^2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^3"); str += "^3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^"); str += "^"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "!"); str += "!"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "√"); str += "g"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "e"); str += "e"; //str += "2.7182818284590452354"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "ln"); str += "l"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "log"); str += "o"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "%"); str += "*0.01"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "sin"); str += "s"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "cos"); str += "c"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "tan"); str += "t"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "π"); str += "p"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "+"); str += "+"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (str != ""){ estimate(); zhanDui(); } else { str = ""; } } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "7"); str += "7"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "8"); str += "8"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "9"); str += "9"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "0"); str += "0"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "-"); str += "-"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "4"); str += "4"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "5"); str += "5"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "6"); str += "6"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "."); str += "."; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "*"); str += "*"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1"); str += "1"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "2"); str += "2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "3"); str += "3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(""); str = ""; indexYN = 0; } }); buttons[tep].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "÷"); str += "/"; } }); }
完整代码
直接拷贝到Java中就可以用:
一个类走完程序。
main函数中还可以设置面板风格。有
- Niumbus风格
- Windows风格
- Windows经典风格
三种风格可以自定义选择,我个人觉得Niumbus风格比较好看。选择哪一个就释放哪一个,把另外两个注释掉就可以了。
package com.lmdxyt; import javax.swing.*; import javax.swing.plaf.FontUIResource; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; import java.util.Stack; public class JSQ { private JFrame jFrame = new JFrame("计算器"); private FontUIResource f = new FontUIResource("隶书", 1, 20); private FontUIResource f1 = new FontUIResource("楷书", 0, 35); private JPanel jPanel = new JPanel(); private int buttonx = 100; private int buttony = 50; private int yy = 50; private JTextField jTextField1 = new JTextField("0", 30); private JTextField jTextField2 = new JTextField("输入要求在main()中", 30); private String str = ""; private String temp = ""; private int indexYN = 0; private String[] strings = { "(", ")", "1/x", "x^2", "x^3", "x^y", "x!", "√", "e", "ln", "log", "%", "sin", "cos", "tan", "π", "+", "=", "7", "8", "9", "0", "-", "4", "5", "6", ".", "*", "1", "2", "3", "c", "÷" }; private JButton[] buttons = new JButton[33]; public void loAsi(){ int tep = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 6; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } int lo = 0; for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j++) { buttons[lo++].setBounds(buttonx * j, yy * (2 + i), buttonx, buttony); } } for (int i = 0; i < 5; i++) { buttons[lo++].setBounds(buttonx * i, yy * 4, buttonx, buttony); } buttons[lo++].setBounds(buttonx * 5, yy * 4, buttonx, buttony * 4); for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[lo++].setBounds(buttonx * j, yy * (5 + i), buttonx, buttony); } } jTextField1.setBounds(0, yy, 600, yy); jTextField1.setFont(f1); jTextField1.setHorizontalAlignment(JLabel.RIGHT); jTextField1.setEditable(false); jTextField1.setBackground(Color.WHITE); jTextField2.setBounds(0, 0, 600, yy); jTextField2.setFont(f1); jTextField2.setHorizontalAlignment(JLabel.RIGHT); jTextField2.setEditable(false); jTextField2.setBackground(Color.WHITE); } public void initButton(){//把按钮添加到jPanel中 this.loAsi(); jPanel.add(jTextField1); jPanel.add(jTextField2); for (int i = 0; i < buttons.length; i++) { jPanel.add(buttons[i]); } jPanel.setLayout(null); } private List<String> zhongZhui(String str) {//把输入的字符串转换成中缀表达式。存入list中 int index = 0; List<String> list = new ArrayList<>(); do{ char ch = str.charAt(index); if("+-*/^!logsct()".indexOf(str.charAt(index)) >= 0){ //是操作符,直接添加至list中 index ++; list.add(ch+""); }else if (str.charAt(index) == 'e' || str.charAt(index) == 'p'){ index ++; list.add(ch+""); } else if("0123456789".indexOf(str.charAt(index)) >= 0){ //是数字,判断多位数的情况 String str1 = ""; while (index < str.length() && "0123456789.".indexOf(str.charAt(index)) >= 0){ str1 += str.charAt(index); index ++; } list.add(str1); } }while (index < str.length()); return list; } public List<String> houZhui(List<String> list){//中缀表达式转换称后缀表达式 Stack<String> fuZhan = new Stack<>(); List<String> list2 = new ArrayList<>(); if (!list.isEmpty()) { for (int i = 0; i < list.size(); i++) { if (isNumber(list.get(i))){ list2.add(list.get(i)); } else if (list.get(i).charAt(0) == '('){ fuZhan.push(list.get(i)); } else if (isOperator(list.get(i)) && list.get(i).charAt(0) != '('){ if (fuZhan.isEmpty()){ fuZhan.push(list.get(i)); } else {//符栈不为空 if (list.get(i).charAt(0) != ')'){ if (adv(fuZhan.peek()) <= adv(list.get(i))){ //入栈 fuZhan.push(list.get(i)); } else {//出栈 while (!fuZhan.isEmpty() && !"(".equals(fuZhan.peek())){ if(adv(list.get(i)) <= adv(fuZhan.peek())){ list2.add(fuZhan.pop()); } } if (fuZhan.isEmpty() || fuZhan.peek().charAt(0) == '('){ fuZhan.push(list.get(i)); } } } else if (list.get(i).charAt(0) == ')'){ while (fuZhan.peek().charAt(0) != '('){ list2.add(fuZhan.pop()); } fuZhan.pop(); } } } } while (!fuZhan.isEmpty()){ list2.add(fuZhan.pop()); } } else { jTextField1.setText(""); } return list2; } public static boolean isOperator(String op){//判断是否为操作符 if ("0123456789.ep".indexOf(op.charAt(0)) == -1) { return true; } else { return false; } } public static boolean isNumber(String num){//判断是否为操作数 if ("0123456789ep".indexOf(num.charAt(0)) >= 0) { return true; } else { return false; } } public static int adv(String f){//判断操作符的优先级 int result = 0; switch(f) { case "+": result = 1; break; case "-": result = 1; break; case "*": result = 2; break; case "/": result = 2; break; case "^": result = 3; break; case "!": result = 4; break; case "g": result = 4; break; case "l": result = 4; break; case "o": result = 4; break; case "s": result = 4; break; case "c": result = 4; break; case "t": result = 4; break; } return result; } public void buttonLister(){//事件监听器 int tep = 0; buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "("); str += "("; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + ")"); str += ")"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1/"); str += "1/"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^2"); str += "^2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^3"); str += "^3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^"); str += "^"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "!"); str += "!"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "√"); str += "g"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "e"); str += "e"; //str += "2.7182818284590452354"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "ln"); str += "l"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "log"); str += "o"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "%"); str += "*0.01"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "sin"); str += "s"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "cos"); str += "c"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "tan"); str += "t"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "π"); str += "p"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "+"); str += "+"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (str != ""){ estimate(); zhanDui(); } else { str = ""; } } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "7"); str += "7"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "8"); str += "8"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "9"); str += "9"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "0"); str += "0"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "-"); str += "-"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "4"); str += "4"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "5"); str += "5"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "6"); str += "6"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "."); str += "."; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "*"); str += "*"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1"); str += "1"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "2"); str += "2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "3"); str += "3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(""); str = ""; indexYN = 0; } }); buttons[tep].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "÷"); str += "/"; } }); } public void init(){ this.initButton(); this.buttonLister(); jFrame.add(jPanel); jFrame.setSize(614, 437); jFrame.setResizable(false); jFrame.setLocationRelativeTo(null); jFrame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); jFrame.setVisible(true); } public void estimate(){//判断输入是否错误 int i = 0; if (str.length() == 0){ } if (str.length() == 1){ //当只有一位字符时,只能是“0123456789ep”中的一个 if ("0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } } if (str.length() > 1){ for (i = 0; i < str.length() - 1; i++) { //1.第一个字符只能为"losctg(0123456789ep"中的一个 if ("losctg(0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //2.“+-*/”后面只能是"0123456789losctg(ep"中的一个 if ("+-*/".indexOf(str.charAt(i)) >= 0 && "0123456789losctg(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //3."."后面只能是“0123456789”中的一个 if (str.charAt(i) == '.' && "0123456789".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //4."!"后面只能是“+-*/^)”中的一个 if (str.charAt(i) == '!' && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //5."losctg"后面只能是“0123456789(ep”中的一个 if ("losctg".indexOf(str.charAt(i)) >= 0 && "0123456789(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //6."0"的判断操作 if (str.charAt(0) == '0' && str.charAt(1) == '0'){ jTextField1.setText("输入错误!"); indexYN = 1; } if (i >= 1 && str.charAt(i) == '0'){ //&& str.charAt(0) == '0' && str.charAt(1) == '0' int m = i; int n = i; int is = 0; //1.当0的上一个字符不为"0123456789."时,后一位只能是“+-*/.!^)”中的一个 if ("0123456789.".indexOf(str.charAt(m - 1)) == -1 && "+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //2.如果0的上一位为“.”,则后一位只能是“0123456789+-*/.^)”中的一个 if (str.charAt(m - 1) == '.' && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } n -= 1; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } //3.如果0到上一个运算符之间没有“.”的话,整数位第一个只能是“123456789”, // 且后一位只能是“0123456789+-*/.!^)”中的一个。 if ((is == 0 && str.charAt(n) == '0') || "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //4.如果0到上一个运算符之间有一个“.”的话,则后一位只能是“0123456789+-*/.^)”中的一个 if (is == 1 && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } if (is > 1){ jTextField1.setText("输入错误!"); indexYN = 1; } } //7."123456789"后面只能是“0123456789+-*/.!^)”中的一个 if ("123456789".indexOf(str.charAt(i)) >= 0 && "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //8."("后面只能是“0123456789locstg()ep”中的一个 if (str.charAt(i) == '(' && "0123456789locstg()ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //9.")"后面只能是“+-*/!^)”中的一个 if (str.charAt(i) == ')' && "+-*/!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //10.最后一位字符只能是“0123456789!)ep”中的一个 if ("0123456789!)ep".indexOf(str.charAt(str.length() - 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } //12.不能有多个“.” if (i > 2 && str.charAt(i) == '.'){ int n = i - 1; int is = 0; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } if (is > 0){ jTextField1.setText("输入错误!"); indexYN = 1; } } //13."ep"后面只能是“+-*/^)”中的一个 if ("ep".indexOf(str.charAt(i)) >= 0 && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("输入错误!"); indexYN = 1; } } } } public double math(List<String> list2) {//通过后缀表达式进行计算 Stack<String> stack = new Stack<String>(); for (int i = 0; i < list2.size(); i++) { if (isNumber(list2.get(i))) { if (list2.get(i).charAt(0) == 'e'){ stack.push(String.valueOf(Math.E)); } else if (list2.get(i).charAt(0) == 'p'){ stack.push(String.valueOf(Math.PI)); } else { stack.push(list2.get(i)); } } else if (isOperator(list2.get(i))){ double res = 0; if (list2.get(i).equals("+")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 + num2; } else if (list2.get(i).equals("-")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 - num2; } else if (list2.get(i).equals("*")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 * num2; } else if (list2.get(i).equals("/")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); if (num2 != 0){ res = num1 / num2; } else { jTextField1.setText("除数不能为0"); indexYN = 1; } } else if (list2.get(i).equals("^")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = Math.pow(num1, num2); } else if (list2.get(i).equals("!")) { double num1 = Double.parseDouble(stack.pop()); if (num1 == 0 || num1 == 1){ res = 1; } else if (num1 == (int)num1 && num1 > 1){ int d = 1; for (int j = (int)num1; j >0; j--) { d *= j; } res = d; } else { jTextField1.setText("阶乘必须为自然数"); indexYN = 1; } } else if (list2.get(i).equals("g")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sqrt(num1); } else if (list2.get(i).equals("l")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1); } else { jTextField1.setText("ln的x必须大于0"); indexYN = 1; } } else if (list2.get(i).equals("o")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1) / Math.log(2); } else { jTextField1.setText("log的x必须大于0"); indexYN = 1; } } else if (list2.get(i).equals("s")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sin(num1); } else if (list2.get(i).equals("c")) { double num1 = Double.parseDouble(stack.pop()); res = Math.cos(num1); } else if (list2.get(i).equals("t")) { double num1 = Double.parseDouble(stack.pop()); if (Math.cos(num1) != 0){ res = Math.tan(num1); } else { jTextField1.setText("tan的x不能为+-(π/2 + kπ)"); indexYN = 1; } } stack.push("" + res); } } if (indexYN == 0){ if (!stack.isEmpty()){ return Double.parseDouble(stack.pop()); } else { return 0; } } else { return -999999; } } public void zhanDui(){//进行计算,并且判断括号是否匹配 String khao = ""; int leftkh = 0; int rightkh = 0; int m = 0; //判断括号是否成对 for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '('){ khao += '('; leftkh++; } if (str.charAt(i) == ')'){ khao += ')'; rightkh++; } } if (leftkh != rightkh){ jTextField1.setText("输入错误!括号不匹配"); indexYN = 1; } if ((leftkh == 0 && rightkh == 0) || ((leftkh == rightkh && leftkh > 0) && khao.charAt(0) == '(' && khao.charAt(khao.length() - 1) == ')')){ if (indexYN == 0){ List<String> list1 = zhongZhui(str); //System.out.println(list1); List<String> list2 = houZhui(list1); //System.out.println(list2); if (indexYN == 0){ if (math(list2) == -999999){ jTextField1.setText(jTextField1.getText()); } else { jTextField1.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); } } } } else { jTextField1.setText("输入错误!括号不匹配"); indexYN = 1; } } public static void main(String[] args) { /* * 1.在输入过程中每两个数值之间必须有运算符,否则报错. * 例如:错误:2ln4(5+8), 2sin2 等 * 正确:2*ln4*(5+8), 2*sin2 * 2.不支持负数,要想得到负数,只能0-x * 例如:错误:-2+3*(-2*6) * 正确:0-2+3*((0-2)+6) * */ new JSQ().init(); //Niumbus风格 try { UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } /*//Windows风格 try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (UnsupportedLookAndFeelException ex) { ex.printStackTrace(); }*/ /* //Windows经典风格 try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (UnsupportedLookAndFeelException ex) { ex.printStackTrace(); }*/ } }
总结
到此这篇关于java实现科学计算器的文章就介绍到这了,更多相关java科学计算器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!