博客
关于我
Java —— 计算器(前端+后台)
阅读量:301 次
发布时间:2019-03-03

本文共 7997 字,大约阅读时间需要 26 分钟。

Java —— 计算器(前端+后台)

要求:

  • 可以计算整型也可以计算浮点型
  • 可以计算带括号的四则运算
  • 当结果为整数时不带小数点
  • 算出结果后若还有运算操作则结果就是第一个输入
  • 可退格和清空
  • 消除double运算的误差,若是无限循环小数则四舍五入保留两位小数

参考界面如下:

在这里插入图片描述
整型运算测试:

输入

在这里插入图片描述
输出
在这里插入图片描述
浮点型运算测试:

输入

在这里插入图片描述
输出
在这里插入图片描述
四舍五入保留两位小数测试:
在这里插入图片描述
运算结果:
在这里插入图片描述

前端代码如下:

Calc.java

package test1;import java.awt.*;import javax.swing.*;public class Calc extends JFrame {   	private void initFrame() {   		try {   			UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");		} catch (Exception e) {   			e.printStackTrace();		}		this.setSize(300, 400); // 窗口大小		this.setTitle("计算器"); // 窗口的名称		this.setLocationRelativeTo(null); // 窗口在屏幕的位置 默认中央		this.setDefaultCloseOperation(this.EXIT_ON_CLOSE); // 设置单击窗口右上角后,程序的处理		this.setLayout(null); // 布局格式 默认		JTextField jtf = this.topSurfacee(); // 调用方法		this.bottomSurface(jtf);		this.setVisible(true); // 设置窗口是否可见 !放在前面窗口无内容	}	private JTextField topSurfacee() {   		JPanel topPanel = new JPanel(); // 建立面板		topPanel.setBounds(-5, 10, 300, 50); // 窗口的在屏幕的位置		JTextField jtf = new JTextField(15); // 显示结果文本框长度15个字		jtf.setHorizontalAlignment(JTextField.RIGHT);// 设置文件右边往左边输出		jtf.setForeground(Color.red); // 设置组件的前景色		jtf.setFont(new Font("SansSerif", Font.PLAIN, 20)); // 字体样式 字体格式 字体大小		jtf.setEditable(false); // 设置选项不可用		jtf.setText("0"); // 文本框的文字设置为“确定”		topPanel.add(jtf); // 加入组件jtf		this.add(topPanel); // 加入组件topPanel		return jtf;	}	private void bottomSurface(JTextField jtf) {   		JPanel bottomPanel = new JPanel(); // 建立面板		bottomPanel.setBounds(8, 80, 270, 250); // 面板的大小		bottomPanel.setLayout(new GridLayout(5, 4, 5, 4)); // 布局格式 5行4列 行距5 列距4		String[] buttonValue = {    "1", "2", "3", "/", // 操作对应的字符串数组				"4", "5", "6", "*", "7", "8", "9", "-", "(", "0", ")", "+", "C", "←", ".", "=" };		calculation cl = new calculation(jtf); // 监听器的创建		for (int i = 0; i < buttonValue.length; i++) {    // 遍历操作字符			JButton button = new JButton(buttonValue[i]); // 建立有文字的按钮			button.setBorder(BorderFactory.createRaisedBevelBorder());			button.setFont(new Font("楷体", 0, 25)); // 字体样式 字体格式 字体大小			button.setForeground(Color.black); // 设置组件的前景色			bottomPanel.add(button); // 添加组件			button.addActionListener(cl);		}		this.add(bottomPanel); // 添加组件	}	public static void main(String[] args) {   		Calc calc = new Calc();		calc.initFrame();	}}

后台代码如下:

calculation.java

package test1;import java.util.*;import java.math.*;  import javax.swing.JTextField;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;public class calculation implements ActionListener {   	private JTextField jtf;	String content = "";	StringBuffer sb = new StringBuffer(); // 创建字符缓冲区域	public calculation(JTextField jtf) {    // 构造方法		this.jtf = jtf;	}	@Override	public void actionPerformed(ActionEvent e) {   		String command = e.getActionCommand(); // 返回与此动作相关的命令字符串		switch (command) {   		// case同时写多个条件,数字的基本处理		case "1":		case "2":		case "3":		case "4":		case "5":		case "6":		case "7":		case "8":		case "9":		case "0":		case ".":		case "+":		case "-":		case "*":		case "/":		case "%":		case "(":		case ")":			sb.append(command); // command添加到sb中			jtf.setText(sb.toString().trim()); // 在文本框添加字符串,并且去掉首尾空格			break;		// 清空输入框中内容		case "C":			// 清空StringBuffer			sb.setLength(0);			jtf.setText("0");			break;		// 退格		case "←":			if (sb.length() == 1) {   				sb.deleteCharAt(sb.length() - 1);				jtf.setText("0");			} else {   				sb.deleteCharAt(sb.length() - 1);				jtf.setText(sb.toString().trim());			}			break;		// 四则运算处理		case "=":			String content = jtf.getText(); // 得到字符串			List
expressionList = expressionToList(content.replace(" ", "")); List
suffixList = parseToSuffixExpression(expressionList); double calculateResult = calculate(suffixList); if (isInteger(calculateResult)) { jtf.setText(String.valueOf((int) calculateResult)); sb.setLength(0); sb.append(String.valueOf((int) calculateResult)); } else{ jtf.setText(String.valueOf(calculateResult)); sb.setLength(0); sb.append(String.valueOf(calculateResult)); } break; } } //具体运算实现 private static List
parseToSuffixExpression(List
expressionList) { // 创建一个栈用于保存操作符 Stack
opStack = new Stack<>(); // 创建一个list用于保存后缀表达式 List
suffixList = new ArrayList<>(); for (String item : expressionList) { // 得到数或操作符 if (isOperator(item)) { // 是操作符 判断操作符栈是否为空 if (opStack.isEmpty() || "(".equals(opStack.peek()) || priority(item) > priority(opStack.peek())) { // 为空或者栈顶元素为左括号或者当前操作符大于栈顶操作符直接压栈 opStack.push(item); } else { // 否则将栈中元素出栈如队,直到遇到大于当前操作符或者遇到左括号时 while (!opStack.isEmpty() && !"(".equals(opStack.peek())) { if (priority(item) <= priority(opStack.peek())) { suffixList.add(opStack.pop()); } } // 当前操作符压栈 opStack.push(item); } } else if (isNumber(item)) { // 是数字则直接入队 suffixList.add(item); } else if ("(".equals(item)) { // 是左括号,压栈 opStack.push(item); } else if (")".equals(item)) { // 是右括号 ,将栈中元素弹出入队,直到遇到左括号,左括号出栈,但不入队 while (!opStack.isEmpty()) { if ("(".equals(opStack.peek())) { opStack.pop(); break; } else { suffixList.add(opStack.pop()); } } } else if (".".equals(item)) { // System.out.print('a'); suffixList.add(item); } else { throw new RuntimeException("有非法字符!"); } } // 循环完毕,如果操作符栈中元素不为空,将栈中元素出栈入队 while (!opStack.isEmpty()) { suffixList.add(opStack.pop()); } return suffixList; } // 判断字符串是否为操作符 public static boolean isOperator(String op) { return op.equals("+") || op.equals("-") || op.equals("*") || op.equals("/"); } // 判断是否为整数或者浮点数 public static boolean isNumber(String num) { return num.matches("^([0-9]{1,}[.][0-9]*)$") || num.matches("^([0-9]{1,})$"); } // 判断是不是整数 public static boolean isInteger(Double num) { if (num % 1 == 0) return true; else return false; } // 获取操作符的优先级 public static int priority(String op) { if (op.equals("*") || op.equals("/")) { return 1; } else if (op.equals("+") || op.equals("-")) { return 0; } return -1; } // 为方便操作将表达式转为list private static List
expressionToList(String expression) { int index = 0; List
list = new ArrayList<>(); do { char ch = expression.charAt(index); if (ch != 46 && (ch <= 47 || ch >= 58)) { // 是操作符,直接添加至list中 index++; list.add(ch + ""); } else { // 是数字,判断多位数的情况 String str = ""; while (index < expression.length() && (expression.charAt(index) > 47 && expression.charAt(index) < 58 || expression.charAt(index) == 46)) { str += expression.charAt(index); index++; } list.add(str); } } while (index < expression.length()); return list; } // 根据后缀表达式list计算结果 private static double calculate(List
list) { Stack
stack = new Stack<>(); for (int i = 0; i < list.size(); i++) { String item = list.get(i); if (item.matches("^([0-9]{1,}[.][0-9]*)$") || item.matches("^([0-9]{1,})$")) { // 是数字(整型或者浮点型) stack.push(Double.parseDouble(item)); } else { // 是操作符,取出栈顶两个元素 double num2 = stack.pop(); double num1 = stack.pop(); double res = 0; if (item.equals("+")) { res = ArithUtil.add(num1, num2); } else if (item.equals("-")) { res = ArithUtil.sub(num1, num2); } else if (item.equals("*")) { res = ArithUtil.mul(num1, num2); } else if (item.equals("/")) { res = ArithUtil.div(num1, num2,2); } else { throw new RuntimeException("运算符错误!"); } stack.push(res); } } return stack.pop(); }}//double型精确计算class ArithUtil{ private ArithUtil(){ } //精确的加法算法 public static double add(double d1,double d2){ BigDecimal b1=new BigDecimal(Double.toString(d1)); BigDecimal b2=new BigDecimal(Double.toString(d2)); return b1.add(b2).doubleValue(); } //精确的减法算法 public static double sub(double d1,double d2){ BigDecimal b1=new BigDecimal(Double.toString(d1)); BigDecimal b2=new BigDecimal(Double.toString(d2)); return b1.subtract(b2).doubleValue(); } //精确的乘法算法 public static double mul(double d1,double d2){ BigDecimal b1=new BigDecimal(Double.toString(d1)); BigDecimal b2=new BigDecimal(Double.toString(d2)); return b1.multiply(b2).doubleValue(); } //相对精确的除法运算,当发生除不尽的情况时,精确到小数点以后2位 public static double div(double d1,double d2,int scale){ BigDecimal b1=new BigDecimal(Double.toString(d1)); BigDecimal b2=new BigDecimal(Double.toString(d2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } }

转载地址:http://kpil.baihongyu.com/

你可能感兴趣的文章
MySQL8找不到my.ini配置文件以及报sql_mode=only_full_group_by解决方案
查看>>
mysql8的安装与卸载
查看>>
MySQL8,体验不一样的安装方式!
查看>>
MySQL: Host '127.0.0.1' is not allowed to connect to this MySQL server
查看>>
Mysql: 对换(替换)两条记录的同一个字段值
查看>>
mysql:Can‘t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock‘解决方法
查看>>
MYSQL:基础——3N范式的表结构设计
查看>>
MYSQL:基础——触发器
查看>>
Mysql:连接报错“closing inbound before receiving peer‘s close_notify”
查看>>
mysqlbinlog报错unknown variable ‘default-character-set=utf8mb4‘
查看>>
mysqldump 参数--lock-tables浅析
查看>>
mysqldump 导出中文乱码
查看>>
mysqldump 导出数据库中每张表的前n条
查看>>
mysqldump: Got error: 1044: Access denied for user ‘xx’@’xx’ to database ‘xx’ when using LOCK TABLES
查看>>
Mysqldump参数大全(参数来源于mysql5.5.19源码)
查看>>
mysqldump备份时忽略某些表
查看>>
mysqldump实现数据备份及灾难恢复
查看>>
mysqldump数据库备份无法进行操作只能查询 --single-transaction
查看>>
mysqldump的一些用法
查看>>
mysqli
查看>>