java新手,写了个简单的计算器,求高手指点一二

package y2019.m08.d24;

import java.awt.*;
import java.awt.event.*;
import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 简单的计算器
 * 
 * @author luther
 * @日期 2019.8.25
 * @version 1.0
 * 
 * 有待优化的地方 BUG:
 * 1,Button增加回退按键监听
 * 2,增加括号运算(),指数运算
 * 3,界面优化
 * 4,末尾去0和小数点
 * 5,文本框全选输入时 覆盖
 * 6,增加回退,清空,括号等Button按键
 * 7,
 * */
public class MyCalc {
	
	public static void main(String[] args) {
		
		new MyCalc().init();
	}
	
	/*
		多次需要使用的正则表达式,
		运算符,减号需要转义,否则表示范围了,如[a-z];
		运算数,包含整数或小数
	*/
	private static final String OPERS = "[\\+\\-\\*/]";
	private static final String NUMBER = "((\\d+\\.\\d*)|\\d+)";
	
	//定义是否刚刚进行过计算,用于下一次输入前清空文本框
	private boolean isDoCalc = false;
	
	//按键4*4按钮文本
	private static final String[] BUTTS = {
							"7", "8", "9", "+", "4", "5", "6", "-", 
							"1", "2", "3", "*", "0", ".", "=", "/"};
	
	//按键4*4按钮
	private Button[] bs = new Button[BUTTS.length];
	
	//主窗口,使用默认的5方向管理器
	private Frame f = new Frame("计算器");
	
	//输入框
	private TextField tf = new TextField(30);
	
	//4*4按键区
	private Panel p = new Panel(new GridLayout(4, 4));
	
	/**
	 * 初始化入口
	 */
	public void init() {
		
		//输入框背景色,银色
		tf.setBackground(new Color(0xE6E8FA));
		
		//输入框注册按键监听器,实现1,ESC退出程序,
		//2,计算后,清空文本区;3,Enter回车键进行计算
		tf.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				
				if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
					System.exit(0);
				}
				else if(isDoCalc) {
					tf.setText("");
					isDoCalc = false;
				}
				else if(e.getKeyCode() == KeyEvent.VK_ENTER){
					doCalc();
				}
			}
		});

		//4*4按钮Button监听器
		ActionListener bListener = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(e.getActionCommand().equals("=")) {
					doCalc();
				}
				else{
					String cmd = e.getActionCommand();
					tf.setText(isDoCalc ? (isDoCalc = false) ? "" : cmd : tf.getText() + cmd);
				}
			}
		};
		
		//4*4按键监听器
		KeyAdapter bkListener = new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				String code = KeyEvent.getKeyText(e.getKeyCode());
				if(code.equals("Enter")) {
					doCalc();
				}
				else if(code.startsWith("NumPad") || code.matches("\\d")) {
					code = code.substring(code.length() - 1);
					tf.setText(isDoCalc ? (isDoCalc = false) ? "" : code : tf.getText() + code);
				}
				else{
					//System.out.println(code);
				}
				
			}
		};
		
		//初始化按键,注册监听器ActionListener和KeyListener,并组合成4*4按键区
		for(int i = 0; i < BUTTS.length; i++) {
			bs[i] = new Button(BUTTS[i]);
			bs[i].addActionListener(bListener);
			bs[i].addKeyListener(bkListener);
			p.add(bs[i]);
		}
		
		//Frame注册WindowListener监听器,实现关闭按钮
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				Runtime.getRuntime().exit(0);
			}
		});
	
		//Frame组合,初始化
		f.add(tf, BorderLayout.NORTH);
		f.add(p);
		f.setLocation(800, 300);
		f.pack();
		f.setVisible(true);
	}
	
	/**
	 * 获取计算表达式,显示计算结果
	 */
	private void doCalc() {
		
		tf.setText(recCalc(tf.getText()));
	}
	
	/**
	 * 递归计算recursive algorithm
	 * @param repre 需要计算的字符串
	 * @return 计算的结果
	 */
	private String recCalc(String exp) {
		
		//去掉末尾的小数点和0
		
		//表达式校验1,无法计算的表达式,2只有一个数的表达式,3只需一次计算的表达式,4多次运算
		if(!exp.matches("^" + NUMBER + "(" + OPERS + NUMBER + ")*$")) {
			isDoCalc = true;
			return "无法计算";
		}
		else if(exp.matches(NUMBER)) {
			return exp;
		}
		else if(exp.matches("^" + NUMBER + OPERS + NUMBER + "$")) {
			return simpleCalc(exp);
		}
		else {
			
			//两个字符串:子计算结果和新表达式,进入该分支必定是包含2个运算符及以上
			String subResult = "";
			String result = exp;
			
			//获取子表达式,先获取乘除表达式
			Matcher m = Pattern.compile(NUMBER + "(\\*|/)" + NUMBER).matcher(exp);
			
			if (m.find()) {
				subResult = m.group();
			}
			else {
				m = Pattern.compile(NUMBER + OPERS + NUMBER).matcher(exp);
				m.find();
				subResult = m.group();
			}
			
			
			//替换子表达式转换成正则表达式即子字符串的+和*需要转义
			String regex = subResult.replaceFirst("\\b+(?=[\\+\\*])", "\\\\");
			
			//把子表达式替换成计算结果
			result = result.replaceFirst(regex, simpleCalc(subResult));
			
			return recCalc(result);
		}
		
	}
	
	/**
	 * 二目运算,两个数的加减乘除计算,使用BigDecimal的精确计算
	 * @param repre 两个需要计算的数,中间带一个运算符
	 * @return 返回计算结果,如果计算失败返回"未知错误!"
	 * */
	private String simpleCalc(String repre) {
		
		//合法性校验
		if(!repre.matches(NUMBER + OPERS + NUMBER)) {
			return "未知错误1!";
		}
		
		//获取运算符
		Matcher m = Pattern.compile(OPERS).matcher(repre);
		m.find();
		String oper = m.group();
		
		//获取2个数字
		String[] nums = repre.split(OPERS);
		BigDecimal b1 = new BigDecimal(nums[0]);
		BigDecimal b2 = new BigDecimal(nums[1]);
		
		//精确计算
		switch (oper) {
		case "+" :
			return b1.add(b2).doubleValue()+"";
		case "-" :
			return b1.subtract(b2).doubleValue()+"";
		case "*" :
			return b1.multiply(b2).doubleValue()+"";
		case "/" :
			return b1.divide(b2, 20, BigDecimal.ROUND_HALF_UP).doubleValue()+"";
		default :
			return "未知错误2!";
		}
	}

}

自己写了一整天,希望大佬能够指点一下,提供下示例代码也好啊
非常感谢!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值