Java实现简易计算器(逆波兰表达式)

Tricia ·
更新时间:2024-11-15
· 1318 次阅读

本文实例为大家分享了Java实现简易计算器的具体代码,供大家参考,具体内容如下

程序的运行环境为Windows10 ,编译环境为IDEA。

计算器有以下功能和要求:能够计算复杂表达式,实现对多位数和负数以及小数的多则复杂计算

已完善功能(Bug):

1,能够计算大数字,小数,负数

2,小数点,运算符等不能连续输入(例如 ..,++,**等)

3,小数点前没有数字时自动补0并在输入框显示“0.”若小数点前是数字,且前面的数字串里含有".",则不能继续输入小数点(“.”---”0.“ ,1.11后面不能继续输入小数点)

4,‘(’左边和‘)’右边输入数字时,有运算符不做操作,无运算符自动补"*",")"后跟"(',在中间加‘*’(例如“7(”--“7*(”,“)7”--“(*7)”,“(1+1)(2+2)”--“(1+1)*(2+2)”)

5,输入的")"不能多于"(",且相邻()之间不能为空(“()”--X,“((1+2)))--X)

6,能计算负数,符号前面没有数字则补0  (-6-1 -- 0-6-1)

7,运算符除"-"号外不能第一个输入,若不是第一次计算,则可以直接输入,将上一个表达式的结果作为此次表达式的第一个运算数   

8,查看历史记录,清空当前记录,清空历史记录,退格操作

运行结果如图:

实现过程: 一、计算器界面设计

1. 初始化界面

通过 this 方法设置包括界面的大小,界面的位置(可根据屏幕设置中间位置),按键北面和中间排版及其颜色和大小,采用GridLayout网格布局

通过循环设置按键的位置,并将运算符加粗,并将所有按键和排版串联到界面上

class Main {     public static class Calculator extends JFrame implements ActionListener {         //  初始化界面         public void init() {             this.setTitle("计算器");             history.setEditable(false);             history.setFont(new Font("宋体", Font.PLAIN, 30));             this.setSize(477, 577); //界面大小             this.setLayout(new BorderLayout());             this.setResizable(false);             this.setLocationRelativeTo(null);   //界面位置设置居中             this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         }         //北面的控件         private final JPanel key_north = new JPanel();         private final JTextField input_text = new JTextField();         private final JTextArea history = new JTextArea();         private final JButton c_btn = new JButton("C");         private final JButton ALLc_btn = new JButton("AC");         //中间的控件         private final JPanel center = new JPanel();         //将界面串联         public Calculator() throws HeadlessException {             this.init();             this.addNorthCompent();             this.addCenterButton();         }         //添加北面控键         public void addNorthCompent() {             this.history.setPreferredSize(new Dimension(350, 200));             this.input_text.setPreferredSize(new Dimension(450, 30));//输入框的大小             input_text.setBackground(new Color(127,255,212));             this.key_north.setBackground(new Color(193,255,193));             this.history.setBackground(new Color(193,255,120));             key_north.add(input_text);             key_north.add(history);             this.c_btn.setForeground(new Color(0,139,139));//按键颜色             this.ALLc_btn.setBackground(new Color(0,205,205));             key_north.add(c_btn);             key_north.add(ALLc_btn);             c_btn.setBackground(Color.CYAN);             c_btn.addActionListener(new ActionListener() {  //为清除操作设置监听                 @Override                 public void actionPerformed(ActionEvent e) {                     firstint = "";                     input_text.setText("");                 }             });             ALLc_btn.addActionListener(new ActionListener() {                 @Override                 public void actionPerformed(ActionEvent e) {                     input_text.setText("");                     firstint = "";                     hitory = "";                     history.setText("");                 }             });             this.add(key_north, BorderLayout.NORTH);         }         //添加中间按键         public void addCenterButton() {             String key_text = "H()←123+456-789*0.=/";//中间控件排版             this.center.setLayout(new GridLayout(5, 4));             String regex = "[+\\-*/=H()←]";             for (int i = 0; i < 20; i++) {  //初始化按键                 String temp = key_text.substring(i, i + 1);                 JButton key = new JButton();                 key.setFont(new Font("宋体",Font.BOLD,20));                 key.setForeground(new Color(69,139,116));                 key.setBackground(new Color(193,255,193));                 key.setText(temp);                 if (temp.matches(regex)) {   //将运算符加粗并更改颜色                     key.setFont(new Font("粗体", Font.BOLD, 30));                     key.setForeground(new Color(102,205,170));                 }                 key.addActionListener(this);                 center.add(key);             }             this.add(center, BorderLayout.CENTER);         }

2. 计算器功能设计

设置监听

设两个空字符串,一个用来保存表达式,另一个用来保存历史记录

为所有按键设置监听功能,将输入的表达式显示到文本框的右边,并实现计算结果,查看历史记录,清空历史记录,计算器表达式退格功能,判断表达式合法性.

@Override public void actionPerformed(ActionEvent e) {   //监听功能             String strings = e.getActionCommand();//保存记录             //JOptionPane.showMessageDialog(this,strings);//监听             if ("0123456789".contains(strings)) {                 if (Objects.equals(firstint, "")) { //输入新的表达式,清除掉上一个表达式结果                     firstint+=strings;                     this.input_text.setText(strings);                     this.input_text.setHorizontalAlignment(JTextField.RIGHT);//显示到右边                 }else if(strings.equals("0")){                     if (Objects.equals(firstint, "0")) {                         this.input_text.setText(firstint);                     }else {                         int index = 0;                         for ( int i=firstint.length()-1;i >=0;i-- ) {                             if(isSymbol(firstint.substring(index))){                                 index=i;                             }                         }                         if (!firstint.substring(index+1, firstint.length() - 1).equals("0")) {                             firstint += strings;                         }                         this.input_text.setText(firstint);                     }                 } else if(firstint.charAt(firstint.length()-1)==')'){  //)后输入数字补*号                     firstint+="*"+strings;                     this.input_text.setText(firstint);                 }else {this.input_text.setText(input_text.getText() + strings);//将输入的数记录并将之前的数放到前面                 this.input_text.setHorizontalAlignment(JTextField.RIGHT);//显示到右边                 firstint += strings;                 System.out.println(firstint);}             } else if (strings.equals(".")) {                 if (Objects.equals(firstint, "")) {                     if (!Objects.equals(ans, "")) {                         firstint = ans + ".";                         this.input_text.setText(firstint);                     }else {this.input_text.setText(input_text.getText() + "0" + strings);                     this.input_text.setHorizontalAlignment(JTextField.RIGHT); //自带补0                     firstint = "0" + strings;}                 } else if(firstint.charAt(firstint.length() - 1) == ')'){ //)后输入小数点补0                     firstint =firstint+ "*0"+strings;                     this.input_text.setText(firstint);                 }                 else if (firstint.charAt(firstint.length() - 1) == '.') {   //不能连续小数点                     this.input_text.setText(firstint);                     this.input_text.setHorizontalAlignment(JTextField.RIGHT);                 } else if (!ToPolland.isNumber(String.valueOf(firstint.charAt(firstint.length() - 1))) && !String.valueOf(firstint.charAt(firstint.length() - 1)).equals(".")) {                     this.input_text.setText(input_text.getText() + "0" + strings);  //前一个既不是数字也不是小数补0                     this.input_text.setHorizontalAlignment(JTextField.RIGHT);                     firstint = firstint + "0" + strings;                 } else if (ToPolland.isNumber(String.valueOf(firstint.charAt(firstint.length() - 1)))) {//如果前面是数字之间输入                     int count = 0, i = 0;                     for (i = firstint.length() - 1; i > 0; i--) {     //查找前面的数字串中有没有小数点                         if (ToPolland.isSymbol(String.valueOf(firstint.charAt(i)))) {                             break;                         }//直到遇到下一个运算符时结束查找                         else if (firstint.charAt(i) == '.') {                             count++;                         }                     }                     if (count == 0) {      //判断前面的数字串没有小数点                         this.input_text.setText(input_text.getText() + strings);                         this.input_text.setHorizontalAlignment(JTextField.RIGHT);                         firstint = firstint + strings;                     }                 }             } else if (strings.matches("[+\\-*/]")) {                 if (Objects.equals(firstint, "")) { //运算符前必须有运算数                     if (!Objects.equals(ans, "")) {                         firstint += ans+strings;                         this.input_text.setText(firstint);                     }                     if(strings.equals("-")){   //减号第一个输入当做负号                         this.input_text.setHorizontalAlignment(JTextField.RIGHT);                         this.input_text.setText("-");                         firstint += strings;                     }                     //JOptionPane.showMessageDialog(null, "请先输入操作数");                 }else if(firstint.charAt(firstint.length()-1)=='.'){  //小数点后不能跟运算符                     this.input_text.setText(firstint);                 }                 else if (firstint.charAt(firstint.length() - 1)=='('){ //(后只能跟-号运算符                     if(strings.equals("-")){                         firstint+=strings;                         this.input_text.setText(firstint);                     }                 }                 else if (ToPolland.isSymbol(String.valueOf(firstint.charAt(firstint.length() - 1)))&&strings!="-") {                     this.input_text.setText(firstint);                 } else {                     this.input_text.setText(input_text.getText() + strings);                     firstint = firstint + strings;                     System.out.println(firstint);                 }             } else if (strings.matches("[()]{1}")) {                 if (strings.equals("(")) {                     if(Objects.equals(firstint, "") ||firstint.charAt(firstint.length()-1)=='('){                         firstint+="(";                         this.input_text.setText(firstint);                         this.input_text.setHorizontalAlignment(JTextField.RIGHT);                     }else if(firstint.charAt(firstint.length() - 1) == ')'){                         firstint+="*"+strings;                         this.input_text.setText(firstint);                     } else if(ToPolland.isNumber(String.valueOf(firstint.charAt(firstint.length()-1)))){                         firstint+="*"+strings;                         this.input_text.setText(firstint);                     }else if(ToPolland.isSymbol(String.valueOf(firstint.charAt(firstint.length()-1)))){                         firstint+=strings;this.input_text.setText(firstint);                     }                     System.out.println(firstint);                 } else if (strings.equals(")") && firstint != "") {                     if(ToPolland.isSymbol(String.valueOf(firstint.charAt(firstint.length()-1)))){                         this.input_text.setText(firstint);                     }else if (firstint.charAt(firstint.length() - 1) != '(') {                         int count1 = 0, count2 = 1;                         for (int i = 0; i < firstint.length(); i++) {  //找出()的个数                             if (firstint.charAt(i) == '(') {                                 count1++;                             }                             if (firstint.charAt(i) == ')') {                                 count2++;                             }                         }                         if (count1 >= count2) {  (个数必须大于等于)个数                             this.input_text.setText(input_text.getText() + strings);                             firstint = firstint + strings;                             System.out.println(firstint);                         }                     }                 }             } else if (strings.equals("=")) {   //计算结果                 try {                     if(firstint.charAt(firstint.length()-1)=='.'){                         firstint=firstint.substring(0,firstint.length()-2);                     }System.out.println(firstint);                     StringBuilder builder = new StringBuilder();                     List<String> list = toPolland(ToPolland.toList(firstint));                     list.forEach(builder::append);                     System.out.println("算式表达式:" + firstint);                     System.out.println("转逆波兰表达式:" + builder);                     System.out.println("转逆波兰表达式计算结果:" + firstint + "=" + ToPolland.calculate(list));                     ans = String.valueOf(ToPolland.calculate(list));                     this.input_text.setText("" + ToPolland.calculate(list));                     hitory += firstint + "=" + ToPolland.calculate(list) + "\n";                     firstint = "";                 } catch (Exception e1) {                     JOptionPane.showMessageDialog(null, "表达式错误");                     firstint = "";                     this.input_text.setText("");                 }             } else if (strings.equals("H")) {   //查看历史记录                 history.setFont(new Font("宋体", Font.BOLD, 20));                 this.history.setText(hitory);             } else if (strings.equals("C")) {   //清空当前记录                 firstint = "";                 this.input_text.setText("");             } else if (strings.equals("AC")) {   //清空历史记录                 firstint = "";                 hitory = "";                 this.history.setText("");                 this.input_text.setText("");             } else if (strings.equals("←") && firstint.length() != 0) {  //退格                 firstint = firstint.substring(0, firstint.length() - 1);                 System.out.println(firstint);                 this.input_text.setText("" + firstint.substring(0, firstint.length()));             }         }     } 二、表达式求值

1、将中缀表达式转为 list 结构

中缀转后缀表达式时需要先将中缀表达式转为 list 结构,在这个过程中,可以分析表达式的合理性,将表达式进行处理(去掉空格及其他错误的符号),判断表达式的正确性并给予反馈 .          我们处理的时候还需要注意多位数字的处理,可以利用一个字符数组对多位数字和小数进行拼接

//将表达式存入list public static List<String> toList(String strings) {         strings = tList(strings);         if (strings == null || strings.length() <= 0) {             throw new NullPointerException("表达式不能为空!");         }         // 去掉不合法的符号         strings = strings.replaceAll("\\s*|\t|\r|\n", "");         List<String> list = new ArrayList<>();         char[] chars = strings.toCharArray();         String ch="",str="";         for (int i = 0; i < chars.length; i++) {             // 判断是否是数字             if (!Character.isDigit((chars[i]))) {                 list.add(String.valueOf(chars[i]));             } else {  //如果是数字,就判断下一个是不是数字,如果是就进行组合(循环),然后录入list                 do {                     ch = String.valueOf(chars[i]);    //读取一个字符                     str += ch;              //进行拼接                     i++;                     //不是最后一个字符,并且下一个还是数字或者小数点,就进行循环                 } while ((i < strings.length()) && ((chars[i] <= 57                         && chars[i] >= 48) || '.' == chars[i]));                 list.add(str);//将拼接的字符串录入到list                 str = "";i--;                 System.out.println(list);//这里一定要将str置位初值             }         }         return list;     }

需要注意的是当输入的表达式中存在负数时,需要在负号前面补0,或者将负号后面的表达式中的一个计算符取反,否则转为逆波兰表达式后得不到正确的结果。

//表达式中存在负数时,后面的逆波兰表达式算法无法得到正确结果,需要补0 public static String tList(String strings) {         String stringBuilder = "";         if(strings.charAt(0)=='-'){//如果第一个字符是‘-',在负号前面补0             stringBuilder+= "0";         }         stringBuilder+=strings.charAt(0); //将第一个‘-'号接到0后面         //如果遇到负号,并且负号前面的符号不是数字,在负号前面补0         for (int i = 1; i < strings.length(); i++) {             if (strings.charAt(i) == '-' && (isNumber(String.valueOf(strings.charAt(i - 1))) == false)) {                 stringBuilder += "0" + strings.charAt(i);             } else stringBuilder += strings.charAt(i);//没有负号则直接拼接         }         return stringBuilder;     }

2、逆波兰表达式的转化(单栈法)

采用单栈来和一个队列对表达式进行操作,也可以采用双栈法处理表达式

构造判断数字,计算符以及优先级的方法

实现代码如下:

//转逆波兰表达式 public static List<String> toPolland(List<String> list) {         Stack<String> s1 = new Stack();         List<String> s2 = new ArrayList<>();         //  从左至右扫描中缀表达式;         for (String item : list) {             // 遇到操作数时,将其压s2;             if (Pattern.matches("-?[0-9]+(\\.[0-9]+)?", item)) {                 s2.add(item);             }//遇到操作符时,比较其与栈顶的操作符的优先级             if (isSymbol(item)) {                 while (s1.size() > 0 && isSymbol(s1.peek()) && priority(item) <= priority(s1.peek())) {                     s2.add(s1.pop());                 }                 s1.push(item);             }             if (item.equals("(")) { //右括号直接入栈                 s1.push(item);             }             if (item.equals(")")) {  //遇到右括号,将左括号之前的操作符全部出栈                 while (!s1.peek().equals("(")) {                     s2.add(s1.pop());                 }                 // 将左边的括号,弹栈                 s1.pop();             }         }         while (s1.size() > 0) {  //将剩余的操作符全部入栈             s2.add(s1.pop());         }         return s2;     }

判断数字和运算符已经比较运算符优先级:

//判断是否为数字 public static boolean isNumber(String str) {         return Pattern.matches("-?[0-9]+(\\.[0-9]+)?", str);     }     //是否是运算符     public static boolean isSymbol(String str) {                 return "+-*/".contains(str);     }     //返回运算符的优先级     public static int priority(String value) {         if ("+-".contains(value)) {             return 1;         } else if ("*/".contains(value)) {             return 2;         } else {             throw new RuntimeException("暂不支持操作符:" + value);         }     }

3、逆波兰表达式(后缀表达式)的计算

首先准备一个栈Res_Stack.

1、从左开始向右遍历后缀表达式的元素。  

2、如果取到的元素是操作数,直接入栈Res_Stack,如果是运算符,从栈中弹出2个数进行运算,然后把运算结果入栈

3、当遍历完后缀表达式时,计算结果就保存在栈里了。

算法思想:

代码如下:

//逆波兰表达式的计算 public static BigDecimal calculate(List<String> nipollands) {         if (nipollands == null || nipollands.size() <= 1) {             throw new NullPointerException("逆波兰表达式列表不能为空!");         }         Stack<BigDecimal> stack = new Stack();         for (String nipolland : nipollands) {             if (isNumber(nipolland)) {   //数字直接入栈                 stack.push(new BigDecimal(nipolland));             } else {      //遇到操作符取出两个数进行对应的计算,并将计算结果入栈                 BigDecimal number1 = stack.pop();                 BigDecimal number2 = stack.pop();                 BigDecimal result;                 switch (nipolland) {                     case "+" -> result=number2.add(number1);                     case "-" -> result=number2.subtract(number1);                     case "*" -> result=number2.multiply(number1);                     case "/" -> result=number2.divide(number1, 3,RoundingMode.HALF_UP);                     default -> throw new RuntimeException("不合法操作符:" + nipolland);                 }                 stack.push(result);//遍历字符串后得到的栈顶既为逆波兰表达式计算结果             }         }         return stack.pop();     }

完整代码:

package com.company; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Stack; import java.util.regex.Pattern; import static com.company.ToPolland.toPolland; class Main {     public static class Calculator extends JFrame implements ActionListener {         //  初始化界面         public void init() {             this.setTitle("计算器");             history.setEditable(false);             history.setFont(new Font("宋体", Font.PLAIN, 30));             this.setSize(477, 577); //界面大小             this.setLayout(new BorderLayout());             this.setResizable(false);             this.setLocationRelativeTo(null);   //界面位置设置居中             this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         }         //北面的控件         private final JPanel key_north = new JPanel();         private final JTextField input_text = new JTextField();         private final JTextArea history = new JTextArea();         private final JButton c_btn = new JButton("C");         private final JButton ALLc_btn = new JButton("AC");         //中间的控件         private final JPanel center = new JPanel();         //将界面串联         public Calculator() throws HeadlessException {             this.init();             this.addNorthCompent();             this.addCenterButton();         }         //添加北面控键         public void addNorthCompent() {             this.history.setPreferredSize(new Dimension(350, 200));             this.input_text.setPreferredSize(new Dimension(450, 30));//输入框的大小             input_text.setBackground(new Color(127,255,212));             this.key_north.setBackground(new Color(193,255,193));             this.history.setBackground(new Color(193,255,120));             key_north.add(input_text);             key_north.add(history);             this.c_btn.setForeground(new Color(0,139,139));//按键颜色             this.ALLc_btn.setBackground(new Color(0,205,205));             key_north.add(c_btn);             key_north.add(ALLc_btn);             c_btn.setBackground(Color.CYAN);             c_btn.addActionListener(new ActionListener() {  //为清除操作设置监听                 @Override                 public void actionPerformed(ActionEvent e) {                     firstint = "";                     input_text.setText("");                 }             });             ALLc_btn.addActionListener(new ActionListener() {                 @Override                 public void actionPerformed(ActionEvent e) {                     input_text.setText("");                     firstint = "";                     hitory = "";                     history.setText("");                 }             });             this.add(key_north, BorderLayout.NORTH);         }         //添加中间按键         public void addCenterButton() {             String key_text = "H()←123+456-789*0.=/";//中间控件排版             this.center.setLayout(new GridLayout(5, 4));             String regex = "[+\\-*/=H()←]";             for (int i = 0; i < 20; i++) {  //初始化按键                 String temp = key_text.substring(i, i + 1);                 JButton key = new JButton();                 key.setFont(new Font("宋体",Font.BOLD,20));                 key.setForeground(new Color(69,139,116));                 key.setBackground(new Color(193,255,193));                 key.setText(temp);                 if (temp.matches(regex)) {   //将运算符加粗并更改颜色                     key.setFont(new Font("粗体", Font.BOLD, 30));                     key.setForeground(new Color(102,205,170));                 }                 key.addActionListener(this);                 center.add(key);             }             this.add(center, BorderLayout.CENTER);         }         private String firstint = "";//保存表达式         static String hitory = "";//保存历史记录         static String ans = "";         @Override         public void actionPerformed(ActionEvent e) {   //监听功能             String strings = e.getActionCommand();//保存记录             //JOptionPane.showMessageDialog(this,strings);//监听             if ("0123456789".contains(strings)) {                 if (firstint == "") {                     firstint+=strings;                     this.input_text.setText(strings);                     this.input_text.setHorizontalAlignment(JTextField.RIGHT);//显示到右边                 }else if(firstint.charAt(firstint.length()-1)==')'){                     firstint+="*"+strings;                     this.input_text.setText(firstint);                 }else {this.input_text.setText(input_text.getText() + strings);//将输入的数记录并将之前的数放到前面                 this.input_text.setHorizontalAlignment(JTextField.RIGHT);//显示到右边                 firstint += strings;                 System.out.println(firstint);}             } else if (strings.equals(".")) {                 if (firstint == "") {                     this.input_text.setText(input_text.getText() + "0" + strings);                     this.input_text.setHorizontalAlignment(JTextField.RIGHT);                     firstint = "0" + strings;                 } else if(firstint.charAt(firstint.length() - 1) == ')'){                     firstint =firstint+ "*0"+strings;                     this.input_text.setText(firstint);                 }                 else if (firstint.charAt(firstint.length() - 1) == '.') {   //不能连续小数点                     this.input_text.setText(firstint);                     this.input_text.setHorizontalAlignment(JTextField.RIGHT);                 } else if (!ToPolland.isNumber(String.valueOf(firstint.charAt(firstint.length() - 1))) && String.valueOf(firstint.charAt(firstint.length() - 1)) != ".") {                     this.input_text.setText(input_text.getText() + "0" + strings);  //前一个既不是数字也不是小数补0                     this.input_text.setHorizontalAlignment(JTextField.RIGHT);                     firstint = firstint + "0" + strings;                 } else if (ToPolland.isNumber(String.valueOf(firstint.charAt(firstint.length() - 1)))) {//如果前面是数字之间输入                     int count = 0, i = 0;                     for (i = firstint.length() - 1; i > 0; i--) {     //查找前面的数字串中有没有小数点                         if (ToPolland.isSymbol(String.valueOf(firstint.charAt(i)))) {                             break;                         }//直到遇到下一个运算符时结束查找                         else if (firstint.charAt(i) == '.') {                             count++;                         }                     }                     if (count == 0) {      //判断前面的数字串没有小数点                         this.input_text.setText(input_text.getText() + strings);                         this.input_text.setHorizontalAlignment(JTextField.RIGHT);                         firstint = firstint + strings;                     }                 }             } else if (strings.matches("[+\\-*/]{1}")) {                 if (firstint == "") {                     if (ans != "") {                         firstint += ans+strings;                         this.input_text.setText(firstint);                     }                     if(strings=="-"){                         firstint += strings;                         this.input_text.setText(input_text.getText()+strings);                     }                     //JOptionPane.showMessageDialog(null, "请先输入操作数");                 } else if (ToPolland.isSymbol(String.valueOf(firstint.charAt(firstint.length() - 1)))&&strings!="-") {                     JOptionPane.showMessageDialog(null, "表达式错误");                 } else {                     this.input_text.setText(input_text.getText() + strings);                     firstint = firstint + strings;                     System.out.println(firstint);                 }             } else if (strings.matches("[()]{1}")) {                 if (strings.equals("(")) {                     if(firstint==""){                         firstint+="(";                         this.input_text.setText(firstint);                         this.input_text.setHorizontalAlignment(JTextField.RIGHT);                     }else if(ToPolland.isNumber(String.valueOf(firstint.charAt(firstint.length()-1)))){                         firstint+="*"+strings;                         this.input_text.setText(firstint);                     }else if(ToPolland.isSymbol(String.valueOf(firstint.charAt(firstint.length()-1)))){                         firstint+=strings;this.input_text.setText(firstint);                     }                     System.out.println(firstint);                 } else if (strings.equals(")") && firstint != "") {                     if (firstint.charAt(firstint.length() - 1) != '(') {                         int count1 = 0, count2 = 1;                         for (int i = 0; i < firstint.length(); i++) {                             if (firstint.charAt(i) == '(') {                                 count1++;                             }                             if (firstint.charAt(i) == ')') {                                 count2++;                             }                         }                         if (count1 >= count2) {                             this.input_text.setText(input_text.getText() + strings);                             firstint = firstint + strings;                             System.out.println(firstint);                         }                     }                 }             } else if (strings.equals("=")) {   //计算结果                 try {                     System.out.println(firstint);                     StringBuilder builder = new StringBuilder();                     List<String> list = toPolland(ToPolland.toList(firstint));                     list.forEach(builder::append);                     System.out.println("算式表达式:" + firstint);                     System.out.println("转逆波兰表达式:" + builder);                     System.out.println("转逆波兰表达式计算结果:" + firstint + "=" + ToPolland.calculate(list));                     ans = String.valueOf(ToPolland.calculate(list));                     this.input_text.setText("" + ToPolland.calculate(list));                     hitory += firstint + "=" + ToPolland.calculate(list) + "\n";                     firstint = "";                 } catch (Exception e1) {                     JOptionPane.showMessageDialog(null, "表达式错误");                     firstint = "";                     this.input_text.setText("");                 }             } else if (strings.equals("H")) {   //查看历史记录                 history.setFont(new Font("宋体", Font.BOLD, 20));                 this.history.setText(hitory);             } else if (strings.equals("C")) {   //清空当前记录                 firstint = "";                 this.input_text.setText("");             } else if (strings.equals("AC")) {   //清空历史记录                 firstint = "";                 hitory = "";                 this.history.setText("");                 this.input_text.setText("");             } else if (strings.equals("←") && firstint.length() != 0) {  //退格                 firstint = firstint.substring(0, firstint.length() - 1);                 System.out.println(firstint);                 this.input_text.setText("" + firstint.substring(0, firstint.length()));             }         }     }     public static void main(String[] args) {         Calculator carculator = new Calculator();         carculator.setVisible(true);     } public class ToPolland {     //表达式中存在负数时,后面的逆波兰表达式算法无法得到正确结果,需要补0     public static String tList(String strings) {         String stringBuilder = "";         if(strings.charAt(0)=='-'){//如果第一个字符是‘-',在负号前面补0             stringBuilder+= "0";         }         stringBuilder+=strings.charAt(0); //将第一个‘-'号接到0后面         //如果遇到负号,并且负号前面的符号不是数字,在负号前面补0         for (int i = 1; i < strings.length(); i++) {             if (strings.charAt(i) == '-' && (!isNumber(String.valueOf(strings.charAt(i - 1))))) {                 stringBuilder += "0" + strings.charAt(i);             } else stringBuilder += strings.charAt(i);//没有负号则直接拼接         }         return stringBuilder;     }     //将表达式存入list     public static List<String> toList(String strings) {         strings = tList(strings);         if (strings == null || strings.length() <= 0) {             throw new NullPointerException("表达式不能为空!");         }         // 去掉不合法的符号         strings = strings.replaceAll("\\s*|\t|\r|\n", "");         List<String> list = new ArrayList<>();         char[] chars = strings.toCharArray();         String ch="",str="";         for (int i = 0; i < chars.length; i++) {             // 判断是否是数字             if (!Character.isDigit((chars[i]))) {                 list.add(String.valueOf(chars[i]));             } else {  //如果是数字,就判断下一个是不是数字,如果是就进行组合(循环),然后录入list                 do {                     ch = String.valueOf(chars[i]);    //读取一个字符                     str += ch;              //进行拼接                     i++;                     //不是最后一个字符,并且下一个还是数字或者小数点,就进行循环                 } while ((i < strings.length()) && ((chars[i] <= 57                         && chars[i] >= 48) || '.' == chars[i]));                 list.add(str);//将拼接的字符串录入到list                 str = "";i--;                 System.out.println(list);//这里一定要将str置位初值             }         }         return list;     }     //转逆波兰表达式     public static List<String> toPolland(List<String> list) {         Stack<String> s1 = new Stack();         List<String> s2 = new ArrayList<>();         //  从左至右扫描中缀表达式;         for (String item : list) {             // 遇到操作数时,将其压s2;             if (Pattern.matches("-?[0-9]+(\\.[0-9]+)?", item)) {                 s2.add(item);             }//遇到操作符时,比较其与栈顶的操作符的优先级             if (isSymbol(item)) {                 while (s1.size() > 0 && isSymbol(s1.peek()) && priority(item) <= priority(s1.peek())) {                     s2.add(s1.pop());                 }                 s1.push(item);             }             if (item.equals("(")) { //右括号直接入栈                 s1.push(item);             }             if (item.equals(")")) {  //遇到右括号,将左括号之前的操作符全部出栈                 while (!s1.peek().equals("(")) {                     s2.add(s1.pop());                 }                 s1.pop();// 将左边的括号,弹栈             }         }         while (s1.size() > 0) {  //将剩余的操作符全部入栈             s2.add(s1.pop());         }         return s2;     }     //逆波兰表达式的计算     public static BigDecimal calculate(List<String> nipollands) {         if (nipollands == null || nipollands.size() <= 1) {             throw new NullPointerException("逆波兰表达式列表不能为空!");         }         Stack<BigDecimal> stack = new Stack();         for (String nipolland : nipollands) {             if (isNumber(nipolland)) {   //数字直接入栈                 stack.push(new BigDecimal(nipolland));             } else {      //遇到操作符取出两个数进行对应的计算,并将计算结果入栈                 BigDecimal number1 = stack.pop();                 BigDecimal number2 = stack.pop();                 BigDecimal result;                 switch (nipolland) {                     case "+" -> result=number2.add(number1);                     case "-" -> result=number2.subtract(number1);                     case "*" -> result=number2.multiply(number1);                     case "/" -> result=number2.divide(number1, 3,RoundingMode.HALF_UP);                     default -> throw new RuntimeException("不合法操作符:" + nipolland);                 }                 stack.push(result);//遍历字符串后得到的栈顶既为逆波兰表达式计算结果             }         }         return stack.pop();     }     //判断是否为数字     public static boolean isNumber(String str) {         return Pattern.matches("-?[0-9]+(\\.[0-9]+)?", str);     }     //是否是运算符     public static boolean isSymbol(String str) {         return "+-*/".contains(str);     }     //返回运算符的优先级     public static int priority(String value) {         if ("+-".contains(value)) {             return 1;         } else if ("*/".contains(value)) {             return 2;         } else {             throw new RuntimeException("暂不支持操作符:" + value);         }     } }



逆波兰表达式 JAVA

需要 登录 后方可回复, 如果你还没有账号请 注册新账号