用Java实现简单计算器功能
作者:杏黄的三叶草 发布时间:2023-03-29 17:44:16
本项目为大家分享了Java实现简单计算器功能的具体代码,供大家参考,具体内容如下
一 项目说明
实训目的:掌握 Java GUI 开发中的布局管理和事件处理机制。
实训要求:
(1)要使用 java 的 GUI 设计出计算器界面。
(2)通过界面按钮,可以实现整数或浮点数的四则运算,并能将结果显示在界面中。
(3)计算可以有小数点,和正负整数的计算。
(4)要有清零功能。
二、类设计
中缀表达式的计算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变量,把该变量转化为字符串输出在文本框中。
四 运行与测试
五 分析与总结
首先,我看到这个题的第一反应是这个界面的布局要用到网格布局,开始我是想直接在触发器里面实现相应的加减乘除功能的,发现如果要计算四则运算有点困难,单个的加减乘除还是挺容易的,后面写了一些代码后,果断删了重写,采用了数据结构中的中缀表达式的计算算法(要用到栈),不过那个时候用的语言是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;
}
}
}
来源:https://blog.csdn.net/dwjdj/article/details/104307986


猜你喜欢
- 我就废话不多说啦,还是直接看代码吧!/** * 设置数据库是否自动提交事务 * @param flag
- 本文实例总结了C#中多态、重载与重写的概念与区别。对于初学C#的朋友来说有不错的参考价值。分享给大家供大家参考。具体分析如下:重写:是指重写
- 由于项目需要在NDK中使用网络开发,对于c语言网络开发来说,libcurl库是个很不错的选择,但android系统中并没有自带该库,所以就得
- 题外话: 泛型与通配符是Java语法中比较难懂的两个语法,学习泛型和通配符的主要目的是能够看懂源码,实际使用的不多。1.泛型1.1泛型的用法
- 前提:windows上安装jdk1.启动jar脚本@echo offSTART "app" javaw -jar app
- 崩溃来源使用过AIDL进行跨进程通信的同学,肯定遇到过DeadObjectException这个崩溃,那么这个崩溃是怎么来的,我们又该如何解
- 背景Timsort 是一个混合、稳定的排序算法,简单来说就是归并排序和二分插入排序算法的混合体,号称世界上最好的排序算法。Timsort一直
- 一、加密介绍本文采用对称式加密算法DES和非对称式加密算法RSA结合做数据传输加密的方式。先说一下对称式加密 DES:对称式加密即使用单钥密
- 具体实现过程不多说了,直接贴代码了。using System;using System.Collections.Generic;using
- Hibernate中有HQL查询语法。但我们用得比较熟的还是数SQL语句,那么应该怎么来让Hibernate支持SQL呢?这个不用我们去考虑
- 1、悲观锁悲观锁假设最坏的情况(如果果你不锁门,那么捣蛋鬼就会闯入并搞得一团糟),只有在确保其他线程不受干扰(获得正确的锁)的情况下才能执行
- 本文实例为大家分享了android自定义控件实现简易时间轴的具体代码,供大家参考,具体内容如下之前项目需要写一个消费记录,类似于时间轴似的控
- 本文实例为大家分享了java web实现简单留言板的具体代码,供大家参考,具体内容如下一、目标用户可以登录并记住密码进入留言板,添加留言,点
- Mybatis判断空字符串先说结论:如果使用正确,是不会产生任何问题的。大家各种疑惑,全是使用不当产生的。先说正确的使用方式一般判空的方式就
- 本文实例为大家分享了Java实现简单ATM机功能的具体代码,供大家参考,具体内容如下项目介绍基于大家使用银行卡在ATM机取款操作,进行相对应
- 本文实例讲述了Android开发之菜单(menu)用法。分享给大家供大家参考,具体如下:Android手机专门用一个按键“menu“来显示菜
- 个人认为,提供params关键字以实现方法形参个数可变是C#语法的一大优点。在方法形参列表中,数组类型的参数前加params关键字,通常可以
- 引言坦白从宽吧,我就是那个花了两天两夜把 1M 图片优化到 100kb 的家伙——王小二!自从因为一
- 本文实例为大家分享了Winform实现石头剪刀布游戏的具体代码,供大家参考,具体内容如下新建一个windows窗体程序,用数字1代表石头,用
- 前言由于业务需要,后端需要返回一个树型结构给前端,包含父子节点的数据已经在数据库中存储好,现在需要做的是如何以树型结构的形式返给给前端。数据