用Java实现简单计算器功能


Posted in Java/Android onJuly 21, 2021

本项目为大家分享了Java实现简单计算器功能的具体代码,供大家参考,具体内容如下

一 项目说明

用Java实现简单计算器功能

实训目的:掌握 Java GUI 开发中的布局管理和事件处理机制。

实训要求:

(1)要使用 java 的 GUI 设计出计算器界面。

(2)通过界面按钮,可以实现整数或浮点数的四则运算,并能将结果显示在界面中。

(3)计算可以有小数点,和正负整数的计算。

(4)要有清零功能。

二、类设计

用Java实现简单计算器功能

中缀表达式的计算solution(String str)
用来中算后缀表达式的值,并将结果返回。准备一个数字栈,一个运算符栈。大致的思路就是遇到,数字直接入数字栈,运算符看优先级进行处理,将要入运算符栈的运算符与栈顶的运算符进行比较,栈顶运算符优先级比较高的话,则把栈顶的运算符弹并且把数字栈的两个数字进行弹出,进行运算,并且把结果再次放到数字栈中,最后剩下的就是最终结果。如果运算符优先级比运算符栈顶的小,则把运算符进栈,最后把运算符都出栈。
计算加减乘除余caculateResult(char optemp, double num1, double num2)
通过传入的optemp(表达式符号)参数。是什么符号就进行什么样的运算
判断符号的优先级getOperlevel(char c)
先乘除后加减,通过0,1,2对运算符的优先级进行标记

三 项目实现设计

首先先设计一个GUI界面,先设置一个JFrame容器,容器中创建两个面板和若干按钮,先把按钮要显示的文字存入字符串数组,然后依次创建几个按钮。在设置一个文本框,用来接收用户输入的内容,centerPanel.setLayout(new GridLayout(4, 4, 12, 16));设置中间面板的布局为网格布局,并指定该容器的行数和列数以及组件之间的水平、垂直间距。centerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));为面板创建一个框,框的头部为5像素,左为5像素,底部为5像素,右为5像素宽。再设置单行文本域的大小,字体,风格和字号,然后为各按钮设置监听器。定义一个StringBuffer类,用于保存触发产生的内容,在用txt.setText(r.toString());方法将内容输出在文本框中,clear按钮触发后,用r.delete(0,r.length());方法清空字符串中的内容并将结果显示在文本框中,“=”按钮是把触发器触发的数字保存StringBuffer里面,然后用该类的toString()方法返回StringBuffer缓冲区中的字符对象,用String类型的变量接收,该字符串接收到的就是一个中缀表达式,创建一个类,该类用于将输入的中缀表达式进行计算,把计算的结果返回给“=”按钮触发器中的result变量,把该变量转化为字符串输出在文本框中。

四 运行与测试

用Java实现简单计算器功能
用Java实现简单计算器功能
用Java实现简单计算器功能
用Java实现简单计算器功能
用Java实现简单计算器功能
用Java实现简单计算器功能
用Java实现简单计算器功能
用Java实现简单计算器功能
用Java实现简单计算器功能

五 分析与总结

首先,我看到这个题的第一反应是这个界面的布局要用到网格布局,开始我是想直接在触发器里面实现相应的加减乘除功能的,发现如果要计算四则运算有点困难,单个的加减乘除还是挺容易的,后面写了一些代码后,果断删了重写,采用了数据结构中的中缀表达式的计算算法(要用到栈),不过那个时候用的语言是C语言,所以关于栈的书写就只能去百度了,之后我知道了栈和他的有关方法,自己也尝试这写了一段代码进行了测试,更加熟练的掌握了栈的用法。

还顺便看了一下广大网友的代码和算法,发现都大同小异,我自己也在他们写的算法的基础上写了一段代码,新增加了实现小数四则运算的功能,其中判断运算符的优先级那段代码直接搬运了网上的代码。

经过测试,发现精度有一点问题,运算的结果有时是正确的,有时是无限接近正确结果(小数点后面的小数位太多了),还有就是实现不了负数的运算,但可以实现浮点数的四则运算。以我现在的水平,这个bug暂时还解决不了。所以就没在修改了然后利用对象的调用把运算结果输出在文本框里面。有一段时间这个程序的界面老是显示不出来,控制台console那里老是闪一下就灭了,我也非常纳闷,之前我还可以显示出来的啊,现在怎么就这样的,百度了很久也没找到答案,后面去请教同学,才发现原来我的聊天窗口没有设置为可见frame.setVisible(true);。所以一般在设置容器的时候,就在他的后面写完他的所有属性,不要写完运行出错了,才发现没有写。`

Calculater:

package com.itcase_eight;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.util.Date;

/**
 * @author 罗志刚
 * @date 2020/12/16 22:09
 */
public class Calculater {
    public static void createAndShowGUI() {
        Date date=new Date();
        DateFormat format=DateFormat.getDateInstance(DateFormat.SHORT);
        // 对计算器整体框架的建立start
        JFrame f = new JFrame("计算器");// 窗口
        JPanel centerPanel = new JPanel(); // 中间面板
        JPanel startPanel=new JPanel();
        // 初始化功能键
        JButton  left=new JButton("(");
        JLabel  data=new JLabel(format.format(date),JLabel.CENTER);
        data.setFont(new Font("Times New Roman",Font.BOLD,17));
        JButton clear=new JButton("Clear");
        JButton  right=new JButton(")");
        String button[] = { "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", ".", "0", "=", "+"};
        JButton but0 = new JButton(button[0]);
        JButton but1 = new JButton(button[1]);
        JButton but2 = new JButton(button[2]);
        JButton but3 = new JButton(button[3]);
        JButton but4 = new JButton(button[4]);
        JButton but5 = new JButton(button[5]);
        JButton but6 = new JButton(button[6]);
        JButton but7 = new JButton(button[7]);
        JButton but8 = new JButton(button[8]);
        JButton but9 = new JButton(button[9]);
        JButton but10 = new JButton(button[10]);
        JButton but11 = new JButton(button[11]);
        JButton but12 = new JButton(button[12]);
        JButton but13 = new JButton(button[13]);
        JButton but14 = new JButton(button[14]);
        JButton but15 = new JButton(button[15]);
        // 单行输入文本框
        JTextField txt = new JTextField();
        // 使用网格布局方式
        centerPanel.setLayout(new GridLayout(5, 4, 12, 16)); // 左右上下间隔
        centerPanel.add(left);
        centerPanel.add(clear);
        centerPanel.add(right);
        centerPanel.add(data);
        centerPanel.add(but0);
        centerPanel.add(but1);
        centerPanel.add(but2);
        centerPanel.add(but3);
        centerPanel.add(but4);
        centerPanel.add(but5);
        centerPanel.add(but6);
        centerPanel.add(but7);
        centerPanel.add(but8);
        centerPanel.add(but9);
        centerPanel.add(but10);
        centerPanel.add(but11);
        centerPanel.add(but12);
        centerPanel.add(but13);
        centerPanel.add(but14);
        centerPanel.add(but15);
        centerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        // 设置容器大小
        txt.setPreferredSize(new Dimension(465, 40));
        // 设置字体,风格和字号
        txt.setFont(new Font("宋体", Font.PLAIN, 28));
        f.add(startPanel);
        f.add(txt, BorderLayout.NORTH); // 将单行文本框添加到窗口的 北部
        f.add(centerPanel, BorderLayout.SOUTH); // 将中间面板添加到窗口的南部
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 点X关闭窗口
        f.setLocation(400, 200); // 初始化时定位
        f.setSize(500, 300);
        // 展示JFrame窗口
        f.setVisible(true);
        f.setResizable(false); // 禁止拖曳改变窗口大小
        f.pack(); // 让窗口的大小自适应
        // 对计算器整体框架的建立end
        // 为按钮事件添加自定义监听器start
        StringBuffer r=new StringBuffer();
        but0.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("7");
                txt.setText(r.toString());
            }
        });
        but1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("8");
                txt.setText(r.toString());
            }
        });
        but2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("9");
                txt.setText(r.toString());
            }
        });
        but4.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("4");
                txt.setText(r.toString());
            }
        });
        but5.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("5");
                txt.setText(r.toString());
            }
        });
        but6.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("6");
                txt.setText(r.toString());
            }
        });
        left.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("(");
                txt.setText(r.toString());
            }
        });
        right.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append(")");
                txt.setText(r.toString());
            }
        });
        but8.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("1");
                txt.setText(r.toString());
            }
        });
        but9.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("2");
                txt.setText(r.toString());
            }
        });
        but10.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("3");
                txt.setText(r.toString());
            }
        });
        but13.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("0");
                txt.setText(r.toString());
            }
        });
        but15.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("+");
                txt.setText(r.toString());
            }
        });
        but3.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("/");
                txt.setText(r.toString());
            }
        });
        but7.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("*");
                txt.setText(r.toString());
            }
        });
        but12.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append(".");
                txt.setText(r.toString());
            }
        });
        but11.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("-");
                txt.setText(r.toString());
            }
        });
        clear.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.delete(0,r.length());   //清空字符串中的内容
                txt.setText(r.toString());  //将结果显示在文本框中
            }
        });
        but14.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                r.append("=");
                String str=r.toString();
                txt.setText("");
                double result= Computer.solution(str);
                String string=String.valueOf(result);
                r.delete(0,r.length());
                r.append(string);
                txt.setText(string);
            }
        });
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(Calculater::createAndShowGUI);
    }
}

Computer类:

package com.itcase_eight;

import java.util.Stack;

/**
 * @author 罗志刚
 * @date 2020/12/16 22:05
 */
public class Computer {
    public static double solution(String str) {
        Stack<Double> numStack = new Stack<>();
        Stack<Character> signalStack = new Stack<>();
        int index = 0;// 记录已经执行的符号数
        int len = str.length();
        while (index < len) {
            char c = str.charAt(index); // 取出这一步的符号
            if (c == '(') {
                signalStack.push(c);// 若是左括号就进栈
            }
            // 否则要先判断优先级
            else if (c == '+' || c == '-' || c == '*' || c == '/') {
                int currOperLevel = getOperlevel(c);// 当前符号的优先级
                while (true) {
                    int stackOperLevel = 0;// 栈顶元素的优先级
                    if (!signalStack.isEmpty()) {
                        Object obj = signalStack.peek();
                        stackOperLevel = getOperlevel((char) obj);
                    }
                    // 若当前元素优先级大于栈顶元素的优先级则入栈
                    if (currOperLevel > stackOperLevel) {
                        signalStack.push(c);
                        break;// 直到让比自己优先级高的符号都出栈运算了再把自己进栈
                    } else {// 不能入栈就进行计算
                        try {
                            char optemp = '0';
                            double num1 = 0;
                            double num2 = 0;
                            if (!signalStack.isEmpty()) {
                                optemp = (char) signalStack.pop();// 取出优先级大的那个符号
                            }
                            if (!numStack.isEmpty()) {
                                num1 = (double) numStack.pop();
                                num2 = (double) numStack.pop();// 取出数据栈中的两个数
                            }
                            numStack.push(caculateResult(optemp, num2, num1));// 将算出来的结果数据再次进入数据栈
                        } catch (Exception e) {
                            // TODO: handle exception
                            e.printStackTrace();
                        }
                    }
                }
            } else if (c == ')') {// 右括号就返回栈顶元素,右括号是不进栈的
                while (true) {
                    char theop = (char) signalStack.pop();
                    if (theop == '(') {
                        break;
                    } else {
                        try {
                            double num1 = (double) numStack.pop();
                            double num2 = (double) numStack.pop();
                            numStack.push(caculateResult(theop, num2, num1));// 运算括号内的内容
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            } else if (c >= '0' && c <= '9') {
                int tempIndex = index + 1;
                while (tempIndex < len) {
                    char temp = str.charAt(tempIndex);// 取字符串中处于当前字符的下一位
                    if ((temp >= '0' && temp <= '9') || temp == '.') {
                        tempIndex++;// 若为数字则继续向后取
                    } else {
                        break;// 证明数字去完
                    }
                }
                String numstr = str.substring(index, tempIndex);// 截取这个字符串则为两个符号之间的数字
                try {
                    double numnum = Double.parseDouble(numstr);// 将数字转换成整型便于运算
                    numStack.push(numnum);
                    index = tempIndex - 1;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            index++;
        }
        // 检查符号栈是否为空
        while (true) {
            Object obj = null;
            if (signalStack.isEmpty() == false) {
                obj = signalStack.pop();
            }
            if (obj == null) {
                break;// 为空证明运算已结束
            } else {// 不为空就出栈运算
                char opterTemp = (char) obj;
                double num1 = (double) numStack.pop();
                double num2 = (double) numStack.pop();
                numStack.push(caculateResult(opterTemp, num2, num1));
            }
        }
        double result = 0;
        try {
            result = (double) numStack.pop();
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return result;
    }

    //计算加减乘除余
    private static Double caculateResult(char optemp, double num1, double num2) {

        switch (optemp) {
            case '+':
                return num1 + num2;
            case '-':
                return num1 - num2;
            case '*':
                return num1 * num2;
            case '/':
                return num1 / num2;
        }
        return 0.0;
    }

    //返回符号优先级
    private static int getOperlevel(char c) {

        switch (c) {
            case '(':
                return 0;
            case '+':
            case '-':
                return 1;
            case '*':
            case '/':
                return 2;
            default:
                return 0;
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Java/Android 相关文章推荐
详解JAVA中的OPTIONAL
Jun 14 Java/Android
分析Java中Map的遍历性能问题
Jun 26 Java/Android
Java 数组内置函数toArray详解
Jun 28 Java/Android
HashMap实现保存两个key相同的数据
Jun 30 Java/Android
Java使用httpRequest+Jsoup爬取红蓝球号码
Jul 02 Java/Android
JavaWeb 入门:Hello Servlet
Jul 16 Java/Android
java协程框架quasar和kotlin中的协程对比分析
Feb 24 Java/Android
关于ObjectUtils.isEmpty() 和 null 的区别
Feb 28 Java/Android
零基础学java之带返回值的方法的定义和调用
Apr 10 Java/Android
Java8利用Stream对列表进行去除重复的方法详解
Apr 14 Java/Android
详解Flutter自定义应用程序内键盘的实现方法
Jun 14 Java/Android
Java中的Kotlin 内部类原理
Jun 16 Java/Android
java设计模式--七大原则详解
java设计模式--建造者模式详解
java设计模式--原型模式详解
SpringBoot快速入门详解
java设计模式--三种工厂模式详解
gateway与spring-boot-starter-web冲突问题的解决
Jul 16 #Java/Android
springboot集成springCloud中gateway时启动报错的解决
Jul 16 #Java/Android
You might like
BBS(php &amp; mysql)完整版(二)
2006/10/09 PHP
PHP生成压缩文件实例
2015/02/07 PHP
php比较两个字符串长度的方法
2015/07/13 PHP
php mailer类调用远程SMTP服务器发送邮件实现方法
2016/03/04 PHP
jQuery之ajax技术的详细介绍
2013/06/19 Javascript
js简单实现让文本框内容逐个字的显示出来
2013/10/22 Javascript
jQuery on()方法绑定动态元素的点击事件无响应的解决办法
2016/07/07 Javascript
jQuery获取select选中的option的value值实现方法
2016/08/29 Javascript
js基本算法:冒泡排序,二分查找的简单实例
2016/10/08 Javascript
详解nodejs 文本操作模块-fs模块(五)
2016/12/23 NodeJs
详解vue-cli中的ESlint配置文件eslintrc.js
2017/09/25 Javascript
JS获取一个表单字段中多条数据并转化为json格式
2017/10/17 Javascript
Vue中的scoped实现原理及穿透方法
2018/05/15 Javascript
angular4+百分比进度显示插件用法示例
2019/05/05 Javascript
Vue2.0使用嵌套路由实现页面内容切换/公用一级菜单控制页面内容切换(推荐)
2019/05/08 Javascript
JavaScript Array对象基本方法详解
2019/09/03 Javascript
[02:42]完美大师赛主赛事淘汰赛第三日观众采访
2017/11/25 DOTA
python将xml xsl文件生成html文件存储示例讲解
2013/12/03 Python
Python实现Pig Latin小游戏实例代码
2018/02/02 Python
python计算列表内各元素的个数实例
2018/06/29 Python
python中的decimal类型转换实例详解
2019/06/26 Python
python如何删除文件中重复的字段
2019/07/16 Python
selenium学习教程之定位以及切换frame(iframe)
2021/01/04 Python
Html5 Canvas动画基础碰撞检测的实现
2018/12/06 HTML / CSS
浅析HTML5中的download属性使用
2019/03/13 HTML / CSS
西班牙三叶草药房:Farmacias Trébol
2019/05/03 全球购物
商得四方公司面试题(gid+)
2014/04/30 面试题
毕业设计计划书
2014/01/09 职场文书
幼儿园亲子活动方案
2014/01/29 职场文书
初三学习计划书范文
2014/04/30 职场文书
企业法人代表证明书
2014/09/27 职场文书
2014年人力资源工作总结
2014/11/19 职场文书
罚站检讨书
2015/01/29 职场文书
大学学习委员竞选稿
2015/11/20 职场文书
Golang标准库syscall详解(什么是系统调用)
2021/05/25 Golang
spring IOC容器的Bean管理XML自动装配过程
2022/05/30 Java/Android