Java计算器大作业

学习使用图形用户界面( GUI) 设计实现—个简单的计算器,能进行 +‐ * / 四则运算(注意数字大小的越界考虑,—般计算器输入的数字个数不超过16个)
页面布局设计图
在这里插入图片描述
监听程序设计流程图
在这里插入图片描述
源代码
Calculator.java

package calculatorDemo;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;

public class Calculator implements ActionListener {
    private JFrame frame = new JFrame();

    //计算器上各按键的名字(从上到下,从左到右)
    private String[] keys = {"(",")","Back","/","7","8","9","*","4","5","6","-","1","2","3","+","+/-","0",".","="};
    //计算器上按键的按钮
    private JButton[] buttons = new JButton[keys.length];
    private JButton buttonClear = new JButton("Clear");
    //显示输入式子文本框
    private JTextField inText = new JTextField("");
    //显示计算结果文本框
    private JTextField resultText = new JTextField("0");  
    //标志用户按的是否是整个表达式的第一个数字,或者是运算符后的第一个数字
    private boolean firstDigit = true;
    //输入表达式
    private String expression = "";
    //计算的中间结果
    private double resultNum = 0.0000;   

    public Calculator() {
    	//初始化计算器
    	init();
    	//窗口标题
        frame.setTitle("计算器 -- @author: rimianxing");
        //设置窗口位置及大小
        frame.setSize(500,700);
        frame.setLocation(500,300);
        //允许修改计算器窗口的大小
        frame.setResizable(true);
        //设置窗口可见
        frame.setVisible(true);
        //点关闭则退出程序
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    //初始化计算器
    private void init() {
    	//功能键和运算符颜色
    	Color color1 = new Color(181,181,181);  
    	//等于号专属颜色
    	Color color2 = new Color(126,192,238);  
    	//背景颜色
    	Color color3 = new Color(232,232,232);  
        //建立一个画板放文本框
        JPanel textPanel = new JPanel();
        textPanel.setLayout(new BorderLayout());
        textPanel.add(BorderLayout.NORTH,inText);
        textPanel.add(BorderLayout.CENTER,resultText);
        //设置文本框中文字的字体以及大小,加粗
        inText.setFont(new Font("楷体",Font.BOLD,20));
        resultText.setFont(new Font("楷体",Font.BOLD,43));
        //文本框中的内容采用右对齐方式
        inText.setHorizontalAlignment(JTextField.RIGHT);
        resultText.setHorizontalAlignment(JTextField.RIGHT);
        //不能修改结果文本框
        inText.setEditable(false);
        resultText.setEditable(false);
        //删除文本框的边框
        inText.setBorder(null);  
        resultText.setBorder(null);
        //设置文本框背景颜色
        inText.setBackground(color1);
        resultText.setBackground(color1);

        //初始化计算器上键的按钮,将键放在一个画板内
        JPanel keysPanel = new JPanel();
        //用网格布局器,5行,4列的网格,网格之间的水平方向垂直方向间隔均为2个像素
        keysPanel.setLayout(new GridLayout(5, 4, 2, 2));
        //初始化功能按钮
        for(int i = 0; i < 4; i++) {
            buttons[i] = new JButton(keys[i]);
            keysPanel.add(buttons[i]);
            buttons[i].setBackground(color3);
            buttons[i].setForeground(Color.black);
            buttons[i].setFont(new Font(Font.SERIF, Font.PLAIN, 18));
            //去除按钮的边框
            buttons[i].setBorderPainted(false);  
        }
        //初始化运算符及数字键按钮
        for(int i = 4; i < keys.length; i++) {
            buttons[i] = new JButton(keys[i]);
            keysPanel.add(buttons[i]);
            if((i+1) % 4 == 0) 
            	buttons[i].setBackground(color3);
            else 
            	buttons[i].setBackground(Color.white);
            buttons[i].setForeground(Color.black);
            buttons[i].setFont(new Font(Font.SERIF, Font.PLAIN, 18));
            //去除按钮的边框
            buttons[i].setBorderPainted(false);  
        }
        //'='符键用特殊颜色
        buttons[keys.length-1].setBackground(color2);  
        keysPanel.setBackground(color1);
        
        //建立一个画板放清除按钮
        JPanel clearPanel = new JPanel();
        clearPanel.setLayout(new BorderLayout());
        clearPanel.add(buttonClear);
        buttonClear.setBackground(color3);
        buttonClear.setForeground(Color.black);
        buttonClear.setFont(new Font(Font.SERIF, Font.PLAIN, 18));
        //去除按钮的边框
        buttonClear.setBorderPainted(false);  
        clearPanel.setBackground(color1);        

        //将文本框所在的面板放在北部,将keysPanel面板放在计算器的中部,将清除按钮所在的面板放在南部
        frame.getContentPane().add("North", textPanel);
        frame.getContentPane().add("Center", keysPanel);
        frame.getContentPane().add("South", clearPanel);
        //设置三个面板的边框,尽量还原win10计算器
        textPanel.setBorder(BorderFactory.createMatteBorder(25,3,1,3,color1));
        keysPanel.setBorder(BorderFactory.createMatteBorder(6,3,3,3,color1));
        clearPanel.setBorder(BorderFactory.createMatteBorder(0,3,3,3,color1));

        //为各按钮添加事件监听器,都使用同一个事件监听器。
        for(int i=0; i<keys.length; i++) {
            buttons[i].addActionListener(this);
        }
        buttonClear.addActionListener(this);
    }

    //处理事件
    public void actionPerformed(ActionEvent ev) {
    	//获取事件源
        String command = ev.getActionCommand();  
        if (command.equals("Back")) {
            //用户按了"Back"键
            doBackspace();
        } 
        else if (command.equals("Clear")) {
            //用户按了"Clear"键
            doClear();
        }   
        else if(command.equals("=")) {
        	//用户按了"="键
        	doResult();        	
        }
        else {
        	//更新输入表达式
            doExpression(command);
        }
    }

    //处理Back键被按下的事件
    private void doBackspace() {
        String text = inText.getText();
        int i = text.length();
        if(i > 0) {
        	//退格,将文本最后一个字符去掉
            text = text.substring(0, i - 1);
            expression = expression.substring(0, i - 1);
            if(text.length() == 0) {
                //如果文本框没有内容了,则初始化计算器的各种值
            	inText.setText("");
                firstDigit = true;
                expression = "";
            } 
            else {
                //显示新的文本
            	inText.setText(text);
            }
        }
    }

    //处理Clear键被按下的事件
    private void doClear() {
        //初始化计算器的各种值
    	inText.setText("");
        resultText.setText("0");
        firstDigit = true;
        expression = "";
    }
    
    //处理=键被按下的事件
    private void doResult() {
    	if(expression.equals(""))
    		resultText.setText("请输入表达式");
    	else {
    		resultNum = new Calculate().calculate(expression);    		
            //在long类型数据的取值范围内,结果为小数保留小数点后4位,整数正常输出 
    		if(resultNum <= (Math.pow(2,63)-1) && resultNum >= -Math.pow(2,63)) {
    			long t1;
                double t2;
                t1 = (long)resultNum;
                t2 = resultNum - t1;
                if(t2 == 0) {
                    resultText.setText(String.valueOf(t1));
                } 
                else {
                    resultText.setText(new DecimalFormat("0.0000").format(resultNum));
                }
    		}
    		//否则按科学计数法的形式输出
    		else
                resultText.setText(Double.toString(resultNum));    		
        	firstDigit = true;
    	}
    }

    //处理数字键或操作符被按下的事件
    private void doExpression(String key) {
        if(firstDigit) {
            //输入的为第一个数或操作符
        	if(key.equals("+/-")) {
        		inText.setText("-");
        		key = "!"; 
        	}
        	else	
        		inText.setText(key);
            resultText.setText("0");
            expression = "";
            expression += key;
        }
        else if(key.equals("+/-")) {
        	//如果输入的是+/-,则在表达式后面加上!号表示接下来输入的是负数,但输入文本框显示"-"号
        	inText.setText(inText.getText() + "-");
        	expression += "!";
        }        	
        else {
        	//如果输入的不是+/-,则将数字或操作符附在结果文本框的后面
            inText.setText(inText.getText() + key);
            expression += key;
        }            
        firstDigit = false;
    }

    public static void main(String[] args) {
        new Calculator();
    }
}

Calculate.java

package calculatorDemo;

import java.util.*;

public class Calculate {
    //将表达式转为list
	private List<String> expressionToList(String expression) {
	    int index = 0;
	    List<String> list = new ArrayList<>();
	    do{
	        char ch = expression.charAt(index);
	        if(ch != '!' && (ch < '0' || ch > '9')) {
	            //是操作符,直接添加至list中
	            index ++ ;
	            list.add(ch+"");
	        }
	        else {
	            //是数字(不论正负、整数、小数),判断多位数的情况
	            String s = "";
	            do{
	                s += expression.charAt(index);
	                index ++;
	            }while(index < expression.length() && ((expression.charAt(index) >='0' && expression.charAt(index) <= '9') || expression.charAt(index) == '.'));
	            list.add(s);
	        }
	    }while(index < expression.length());
	    return list;
	}

	//将中缀表达式转换为后缀表达式
	private List<String> parseToSuffixExpression(List<String> expressionList) {
	    //创建一个栈用于保存操作符
	    Stack<String> opStack = new Stack<>();
	    //创建一个list用于保存后缀表达式
	    List<String> 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 {
	            throw new RuntimeException("有非法字符!");
	        }
	    }
	    //循环完毕,如果操作符栈中元素不为空,将栈中元素出栈入队
	    while(!opStack.isEmpty()) {
	        suffixList.add(opStack.pop());
	    }
	    return suffixList;
	}
	
	//判断字符串是否为操作符
	private boolean isOperator(String op) {
	    return op.equals("+") || op.equals("-") || op.equals("*") || op.equals("/");
	}

	//判断是否为数字
	private boolean isNumber(String num) {
		//负数则去掉前面的!号
		if(num.charAt(0) == '!')
			num = num.substring(1, num.length());
		//正则表达式,\\中第1个\为转义字符,匹配整数或小数
	    return num.matches("\\d+(\\.\\d+)?");
	}

	//获取操作符的优先级
	private int priority(String op) {
	    if(op.equals("*") || op.equals("/")) {
	        return 1;
	    }
	    else if(op.equals("+") || op.equals("-")) {
	        return 0;
	    }
	    return -1;
	}

	//根据后缀表达式list计算结果
	public double calculate(String expression) {
		//中缀表达式转为list结构
        List<String> expressionList = expressionToList(expression);
        //将中缀表达式转换为后缀表达式
        List<String> suffixList = parseToSuffixExpression(expressionList);
	    Stack<Double> stack = new Stack<>();
	    for(int i=0;i<suffixList.size();i++) {
	        String item = suffixList.get(i);
	        //负数则去掉前面的!号,并乘上-1
			if(item.charAt(0) == '!') {
				item = item.substring(1, item.length());
				stack.push(-Double.parseDouble(item));
			}				
	        //正数
			else if(item.matches("\\d+(\\.\\d+)?"))	            
	            stack.push(Double.parseDouble(item));
	        else {
	            //是操作符,取出栈顶两个元素,经操作符作用后将结果压栈
	            double num2 = stack.pop();
	            double num1 = stack.pop();
	            double res = 0;
	            if(item.equals("+")) {
	                res = num1 + num2;
	            }
	            else if(item.equals("-")) {
	                res = num1 - num2;
	            }
	            else if(item.equals("*")) {
	                res = num1 * num2;
	            }
	            else if(item.equals("/")) {
	                res = num1 / num2;
	            }
	            else {
	                throw new RuntimeException("运算符错误!");
	            }
	            stack.push(res);
	        }
	    }
	    return stack.pop();
	}
}

测试结果
输入表达式,输出整数
在这里插入图片描述
输出小数,测试+/-、.按钮功能
在这里插入图片描述
0做除数
在这里插入图片描述
在这里插入图片描述
输入为空时按=
在这里插入图片描述
结果<263-1或>-2^63
在这里插入图片描述
在这里插入图片描述
结果>263-1或<-2^63,以科学计数法形式输出
在这里插入图片描述
在这里插入图片描述
16位数*16位数
在这里插入图片描述

总结
  我设计的计算器和win10自带的标准计算器界面相似,但计算处理有所不同。相比之下增加了(、)两个按钮,可以达到输入表达式的目的。文本框第1行用于记录输入表达式,第2行在按下=按钮后显示结果(在long类型的取值范围内整数正常输出,小数则保留4位小数;在long类型的取值范围外以科学记数法显示)。Clear按钮清空文本框第1行,让第2行显示0,并初始化计算器。
  计算方式是重点考虑的地方,我将数据结构的知识与java结合:输入表达式是个中缀表达式,首先将字符串转换成list结构,便于操作;然后通过相关算法将中缀表达式转换成后缀表达式(通过后缀表达式计算具有无需考虑运算符优先级的优点),转换过程中用到了栈;最后利用栈通过后缀表达式求值。
  基于数字大小的越界考虑,中间计算及最终结果都采用double类型。可以改进的地方有:增加指数运算(指数运算可以把平方、开方、倒数运算都包括进去),但是指数运算是从右到左结合的,而±*/的运算顺序是从左到右,处理起来有所困难。由于时间关系,就没有再做进一步的考虑。

  • 4
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
java 大作业 科学计算器 menu切换普通与科学计算器 部分代码: class MyKey extends KeyAdapter { public void keyPressed(KeyEvent e) { char c = e.getKeyChar(); System.out.print(c); boolean bFlag = false; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if(IfResult){ tf.setText(""); IfResult = false; } tf.setText(tf.getText().trim() + c); bFlag = true; break; case '.': if(tf.getText().trim().indexOf(".") == -1){ tf.setText(tf.getText() + "."); } bFlag = true; break; case '_': if(Double.parseDouble(tf.getText()) > 0){ if(tf.getText().length() > 1){ tf.setText(tf.getText().substring(0, tf.getText().length() - 1)); }else{ tf.setText("0"); IfResult = true; } }else{ if(tf.getText().length() > 2){ tf.setText(tf.getText().substring(0, tf.getText().length() - 1)); }else{ tf.setText("0"); IfResult = true; } } bFlag = true; break; case '+': if(flag){ IfResult = false; } if(IfResult){ oper = "+"; }else{ getResult(Double.parseDouble(tf.getText())); oper = "+"; IfResult = true; } bFlag = true; break; case '-': if(flag){ IfResult = false; } if(IfResult){ oper = "-"; }else{ getResult(Double.parseDouble(tf.getText())); oper = "-"; IfResult = true; } bFlag = true; break; case '*': if(flag){ IfResult = false; } if(IfResult){ oper = "*"; }else{ getResult(Double.parseDouble(tf.getText())); oper = "*"; IfResult = true; } bFlag = true; break; case '/': if(flag){ IfResult = false; } if(IfResult){ oper = "/"; }else{ getResult(Double.parseDouble(tf.getText())); oper = "/"; IfResult = true; } bFlag = true; break; case '=': if(flag){ IfResult = false; } if(IfResult){ oper = "="; }else{ getResult(Double.parseDouble(tf.getText())); oper = "="; IfResult = true; } bFlag = true; break; } if(bFlag && tf.getText().equals("0")){ tf.setText("0"); IfResult = true; flag = true; } } }
用来完成大作业的。文档内容: 1 Java技术体系 1.1 Java语言 1.2 Java平台 1.3 Java应用领域 2 Java语言的技术特点 2.1 1 2.2 2 2.3 3 3 Java语言与C++的异同分析总结。 4 选用C和java语言时编程算法程序有什么不同,有什么优势和劣势。 5 自己编程学习的级别和状态。以及自己以后的编程学习的计划和想法。 6 下面3道题目中选一道,给出算法分析和程序。 1)“黄金分割数”在我们的生活中很常见,但是在不同的应用领域,要求的精度也不一样。 例如:三位小数是0.618 现在我们需要你能求出保留100位小数的黄金分割数,采用的算法为“分层计算法”: 黄金数= 1 --------------- 1+ 1 ------------- 1+ 1 ----------- 1+ 1 --------- ..... 注意,计算出的结果,如果第100位为0也需要保留。 2)已知一个数列: 5,2,4,3,7,6 那么,在这个数列中存在这样一些“连续数”,例如:5,2,4,3这个子数列排序后是连续的。同样2,4,3也是连续的,为了方便表示 我们使用下标来标识,这样,这个数列中存在以下“连续数”: [1,1] [1,4] [1,6] [2,2] [2,4] [3,3] [3,4] [4,4] [5,5] [5,6] [6,6] 这样,他就存在11个“连续数”。现在需要你在用户找出一个数组中所有的“连续数”。 要求: 1、用户输入一个整数N,表示下面数组的个数 2、用户每输入一行作为一个数组 如: 用户输入: 1 5,2,4,3,7,6 程序输出: 11 3)有一种数我们称之为幸运数,它的特点是这样的,首先,由自然数按顺序排列: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 … 这样,1比较特殊, 1为第一个幸运数,那么,我们移除掉序号能被2整除的数(注意:是序号,而不是数本身,每次移除后都重新排序)就剩下: 1 3 5 7 9 11 13 15 17 19… 3为第二个幸运数,那么我们需要去掉序号能被3(下一次是除4,然后是5,每次加1)整除的数,5 11 17...剩下: 1 3 7 9 13 15 19… 那么7为第三个幸运数,后面的幸运数,依此类推,移除之后剩下的数字都是幸运数。 现在我们需要你求出给定的m和n之间的幸运数的个数: 例如:给定1 20,那么个数为:5(5个幸运数分别是1,3,7,13,19) 现在要求用户输入两个数m和n(m<n<=1000*1000),输出幸运数的个数。 例如: 用户输入: 1 20 程序输出: 5 格式:小四,1.5倍行距
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值