简易计算器 java 实现_四则混合运算_包括加减乘除带括号和小数运算

calculator

更:修了一点小 bug,解决一开始就是 ’ - ’ 号计算表达式

此项目已打包为 .exe 文件 → download

项目打包方法

此计算器实现了以下界面的全部功能
用到了java.awt java.swing 等库以及堆栈结构

  • 用逆波兰法求解后缀表达式,再根据后缀表达式求解最终算术值

解决了 运算符优先级问题
先看效果:
在这里插入图片描述

解释都在代码里啦,灰常详细 hi✿(。◕ᴗ◕。)✿

StartMyCalculator.java

package calculator;

public class StartMyCalculator {
    public static void main(String[] args) {
    	// 启动计算器图形界面窗口
        new MyGUICalculator();
    }
}

MyGUICalculator.java

package calculator;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.util.Stack;

public class MyGUICalculator implements ActionListener {
    // 定义主窗口并命名
    private final JFrame jf = new JFrame("my calculator");
    // 定义文本框
    private final JTextField jt = new JTextField("请用鼠标点击按钮来输入算术表达式");
    // 定义按钮
    private JButton but_0, but_1, but_2, but_3, but_4, but_5, but_6, but_7, but_8, but_9,
            but_add, but_sub, but_mult, but_div, but_lt, but_rt, but_org, but_equ, but_C, but_Del;
    // 初始化表达式
    private String input = "";

    MyGUICalculator() {
        // 设置各按钮的信息
        setButton();
        // 设置文本框信息
        setTextField();
        //设置主窗口信息
        setThis();
        // 添加各组件
        addBut();
    }

    // 设置按钮信息的方法
    private void setButton() {
        but_0 = new JButton("0");
        but_0.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_0.setMargin(new Insets(0, 0, 0, 0));
        but_1 = new JButton("1");
        but_1.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_1.setMargin(new Insets(0, 0, 0, 0));
        but_2 = new JButton("2");
        but_2.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_2.setMargin(new Insets(0, 0, 0, 0));
        but_3 = new JButton("3");
        but_3.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_3.setMargin(new Insets(0, 0, 0, 0));
        but_4 = new JButton("4");
        but_4.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_4.setMargin(new Insets(0, 0, 0, 0));
        but_5 = new JButton("5");
        but_5.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_5.setMargin(new Insets(0, 0, 0, 0));
        but_6 = new JButton("6");
        but_6.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_6.setMargin(new Insets(0, 0, 0, 0));
        but_7 = new JButton("7");
        but_7.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_7.setMargin(new Insets(0, 0, 0, 0));
        but_8 = new JButton("8");
        but_8.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_8.setMargin(new Insets(0, 0, 0, 0));
        but_9 = new JButton("9");
        but_9.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_9.setMargin(new Insets(0, 0, 0, 0));
        but_add = new JButton("+");
        but_add.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_add.setMargin(new Insets(0, 0, 0, 0));
        but_sub = new JButton("-");
        but_sub.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_sub.setMargin(new Insets(0, 0, 0, 0));
        but_mult = new JButton("*");
        but_mult.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_mult.setMargin(new Insets(0, 0, 0, 0));
        but_div = new JButton("/");
        but_div.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_div.setMargin(new Insets(0, 0, 0, 0));
        but_lt = new JButton("(");
        but_lt.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_lt.setMargin(new Insets(0, 0, 0, 0));
        but_rt = new JButton(")");
        but_rt.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_rt.setMargin(new Insets(0, 0, 0, 0));
        but_Del = new JButton("Del");
        but_Del.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_Del.setMargin(new Insets(0, 0, 0, 0));
        but_C = new JButton("C");
        but_C.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_C.setMargin(new Insets(0, 0, 0, 0));
        but_equ = new JButton("=");
        but_equ.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_equ.setMargin(new Insets(0, 0, 0, 0));
        but_org = new JButton(".");
        but_org.setFont(new Font("楷体_GB2312", Font.BOLD, 18));
        but_org.setMargin(new Insets(0, 0, 0, 0));
    }

    // 设置文本框信息方法
    private void setTextField() {
        jt.setEditable(false);
        jt.setFont(new Font("楷体_2312", Font.PLAIN, 18));
    }

    // 定义主窗口的方法
    private void setThis() {
        // 窗口大小
        jf.setSize(500, 335);
        // 窗口位置
        jf.setLocation(600, 350);
        // 关闭窗口结束程序运行
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 窗口大小不可变
        jf.setResizable(false);
        // 窗口可见
        jf.setVisible(true);
    }

    // 添加各组件的方法
    private void addBut() {
        // 组件绝对位置摆放
        jf.setLayout(null);
        jt.setBounds(0, 0, 500, 80);
        jf.add(jt);
        but_7.setBounds(0, 100, 100, 50);
        jf.add(but_7);
        but_8.setBounds(100, 100, 100, 50);
        jf.add(but_8);
        but_9.setBounds(200, 100, 100, 50);
        jf.add(but_9);
        but_add.setBounds(300, 100, 100, 50);
        jf.add(but_add);
        but_lt.setBounds(400, 100, 100, 50);
        jf.add(but_lt);
        but_4.setBounds(0, 150, 100, 50);
        jf.add(but_4);
        but_5.setBounds(100, 150, 100, 50);
        jf.add(but_5);
        but_6.setBounds(200, 150, 100, 50);
        jf.add(but_6);
        but_sub.setBounds(300, 150, 100, 50);
        jf.add(but_sub);
        but_rt.setBounds(400, 150, 100, 50);
        jf.add(but_rt);
        but_1.setBounds(0, 200, 100, 50);
        jf.add(but_1);
        but_2.setBounds(100, 200, 100, 50);
        jf.add(but_2);
        but_3.setBounds(200, 200, 100, 50);
        jf.add(but_3);
        but_mult.setBounds(300, 200, 100, 50);
        jf.add(but_mult);
        but_Del.setBounds(400, 200, 100, 50);
        jf.add(but_Del);
        but_org.setBounds(0, 250, 100, 50);
        jf.add(but_org);
        but_0.setBounds(100, 250, 100, 50);
        jf.add(but_0);
        but_equ.setBounds(200, 250, 100, 50);
        jf.add(but_equ);
        but_div.setBounds(300, 250, 100, 50);
        jf.add(but_div);
        but_C.setBounds(400, 250, 100, 50);
        jf.add(but_C);
        initial();
    }

    // 各组件添加监听器
    private void initial() {
        but_0.addActionListener(this);
        but_1.addActionListener(this);
        but_2.addActionListener(this);
        but_3.addActionListener(this);
        but_4.addActionListener(this);
        but_5.addActionListener(this);
        but_6.addActionListener(this);
        but_7.addActionListener(this);
        but_8.addActionListener(this);
        but_9.addActionListener(this);
        but_add.addActionListener(this);
        but_sub.addActionListener(this);
        but_mult.addActionListener(this);
        but_div.addActionListener(this);
        but_org.addActionListener(this);
        but_C.addActionListener(this);
        but_lt.addActionListener(this);
        but_rt.addActionListener(this);
        but_Del.addActionListener(this);
        but_equ.addActionListener(this);
    }

    // 遍历到操作符时的压栈方法
    public double cal(double num1, double num2, String operator) {
        double result = 0;
        switch (operator) {
            case "+":
                result = num1 + num2;
                break;
            case "-":
                result = num2 - num1;  //靠近栈底的做被减数
                break;
            case "*":
                result = num1 * num2;
                break;
            case "/":
                // 除数不为 0 则返回结果,除数为 0 弹出提示对话框
                if (num1 != 0) {
                    result = num2 / num1; //靠近栈底的做被除数
                } else {
                    // 提示对话框
                    JOptionPane.showOptionDialog(jf, "除数不能为0", "温馨提示",
                            JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, null, null);
                    input = "";
                    jt.setText(input);
                }
                break;
            default:
                JOptionPane.showOptionDialog(jf, "算术表达式无法计算", "温馨提示您",
                        JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, null, null);
                input = "";
                jt.setText(input);
                break;
        }
        return result;
    }

    // 后缀表达式值算法
    public String calculate(String input) {
        // 遍历字符串 input, 去掉连续两个空格的情况,例 (6+7)/3 + 2
        // 创建字符串数组用 " " 标志分割输入字符串
        String[] compute = input.split(" ");
        Stack<String> stack1 = new Stack<>();  // 存后缀表达式
        Stack<String> stack2 = new Stack<>();  // 临时放操作符
        Stack<String> stack3 = new Stack<>();  // 最后运算栈
        for (int i = 0; i < compute.length; ++i) {
            if (compute[i].matches("-?\\d+(\\.\\d+)?")) {
                stack1.push(compute[i]);
            } else if (stack2.isEmpty()) {
                stack2.push(compute[i]);
            } else if (compute[i].equals("(")) {
                stack2.push(compute[i]);
            } else if (compute[i].equals(")")) {
                while (!(stack2.peek().equals("("))) {
                    stack1.push(stack2.pop());
                }
                stack2.pop();
            }
            // 加减乘除入栈
            else if (compute[i].equals("+") || compute[i].equals("-") || compute[i].equals("*")
                    || compute[i].equals("/") || compute[i].equals("(")) {
                while ((!stack2.isEmpty()) && (nPriority(compute[i]) <= nPriority(stack2.peek()))) {
                    stack1.push(stack2.pop());
                }
                stack2.push(compute[i]);
            }
            // 数字小数点直接入栈
            else stack1.push(compute[i]);
        }
        // 当操作符栈不为空,将操作符全部弹入 stack1
        while (!stack2.isEmpty()) {
            stack1.push(stack2.pop());
        }
        // 遍历后缀表达式
        for (String l : stack1) {
        	String num1, num2;
            // 正则表达式匹配浮点数
            if (l.matches("-?\\d+(\\.\\d+)?")) {
                //if (l.matches("-?\\d+")) {    //正则表达式匹配数字
                stack3.push(l);
            } else {
                if(stack3.isEmpty()){
                    num1 = "0";
                }
                else {
                    num1 = stack3.pop();
                }
                if(stack3.isEmpty()){
                   num2 = "0";
                }
                else {
                    num2 = stack3.pop();
                }
                double calculate = cal(Double.parseDouble(num1), Double.parseDouble(num2), l);
                stack3.push(String.valueOf(calculate));
            }
        }
        // 计算结果保留三位小数
        DecimalFormat df = new DecimalFormat("#0.000");
        return df.format(Double.parseDouble(stack3.pop()));
    }

    // 定义运算符优先级
    public int nPriority(String str) {
        int n = 0;
        switch (str) {
            case "+":
            case "-":
                n = -1;
                break;
            case "*":
            case "/":
                n = 1;
                break;
            case "(":
                n = -2;
                break;
            case ")":
                n = 2;
            default:
                break;
        }
        return n;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        int cnt = 0;
        String actionCommand = e.getActionCommand();            //获取按钮上的字符串
        if (actionCommand.equals("+") || actionCommand.equals("-") || actionCommand.equals("*") || actionCommand.equals("/")) {
            input += " " + actionCommand + " ";
        } else if (actionCommand.equals("Del")) {
            input = input.substring(0, input.length() - 1);
        } else if (actionCommand.equals("C")) {
            input = "";
        } else if (actionCommand.equals("=")) {
            try {
                input += " " + "=" + " " + calculate(input);
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            jt.setText(input);
            input = "";
            cnt = 1;
        } else if (actionCommand.equals("(")) {
            input += actionCommand + " ";
        } else if (actionCommand.equals(")")) {
            input += " " + actionCommand;
        } else input += actionCommand;
        // 设置标志 cnt ,让文本框始终显示输入字符串
        if (cnt == 0) {
            jt.setText(input);
        }
    }
}


注:
基本方法全部实现

但此项目已更新,现已实现比较完美,ღ( ´・ᴗ・` )比心

  • 15
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值