计算数学表达式的程序

目录

一、选题与前期调查

1.选题

2.前期调查

二、项目描述

1.项目简介

2.项目采用技术

3.功能需求分析

4.项目亮点

5.系统细节

三、功能运行结果展示

1.系统主界面

2.实现基本的运算

2.1实现加法运算

2.2实现减法运算

2.3实现乘法运算

2.4实现除法运算

2.5实现四则运算

3.实现基本的数学函数

3.1实现开方

3.2实现平方

3.3实现倒数

3.4实现百分比转换

3.5实现三角函数

3.5.1实现sin

3.5.2实现cos

3.5.3实现tan

3.6实现绝对值

3.7实现十进制转化为二进制

3.8实现十进制转换为十六进制

3.9实现取整

4.实现查看历史运算式和以及结果

四、关键代码

五、使用git管理代码

六、遇到的问题

一、选题与前期调查

1.选题

计算数学表达式的程序(2人)等级:C-

功能要求:

1)由用户输入一个简单的四则运算表达式,求出其计算结果后显示。2)允许在表达式中出现常用的数学函数,如绝对值、取整、三角函数、倒数、平方根、平方、立方等。

注意:该题对算法有一定要求,并且如果要得高分,其中的算法一定要自己写。如果被判定为抄袭,得分不会超过C。

提供多线程网络服务与客户端可提供提升至A。

2.前期调查

1.主要使用gpt3.5和cursor来进行课设完成:

gpt3.5:extension://dhoenijjpgpeimemopealfcbiecgceod/chat/index.html

cursor:Cursor - The AI-first Code Editor


二、人员分工

分工姓名任务
组长罗明

博客编写;GuiMain类;Gui类;Algorithm类;编码规范格式;前期调查和功能设计;git管理代码


三、项目描述

1.项目简介

  • 该项目是一款简单的计算器,主要用于大家平时进行一些简单的计算。

2.项目采用技术

  • GUI图形界面
  • 设计模式
  • git代码管理

3.功能需求分析

  • 支持基本的加减乘除运算
  • 支持复杂的四则运算
  • 支持常用的数学函数
  • 支持清零功能

4.项目亮点

  • 用户友好的界面设计,包括按钮和输入框
  • 实现在显示框得到计算结果
  • 支持历史记录功能,可以查看之前的计算式和计算结果
  • 功能完备,有利于大家轻松入手使用

5.系统细节

5.1系统目录

5.2GuiMain类

  • 系统的主函数,主要是启动一个GUI界面

5.3Gui类

  • 用于加载出计算器的主界面
  • 继承自Frame类,实现ActionListener接口
  • 登录监听器接口,定义登录成功事件回调方法
  • 功能:设计一个GUI界面

5.4Algorithm类

  • 用于记录计算器功能的实现方法
  • 继承自JFrame类,实现ActionListener接口
  • 功能:包含实现计算器每个计算方法和基本数学函数的实现方法

四、功能运行结果展示

1.系统主界面

2.实现基本的运算

2.1实现加法运算

2.2实现减法运算

2.3实现乘法运算

2.4实现除法运算

2.5实现四则运算

3.实现基本的数学函数

3.1实现开方

3.2实现平方

3.3实现倒数

3.4实现百分比转换

3.5实现三角函数

3.5.1实现sin

3.5.2实现cos

3.5.3实现tan

3.6实现绝对值

3.7实现十进制转化为二进制

3.8实现十进制转换为十六进制

3.9实现取整

4.实现查看历史运算式和以及结果


五、关键代码

1.GUI界面设置

public Gui() {
        super("Caculator");//“超”关键字,表示调用父类的构造函数,
        resultText.setBounds(20, 18, 255, 115);     // 设置文本框大小
        resultText.setAlignmentX(RIGHT_ALIGNMENT);  // 文本框内容右对齐
        resultText.setEditable(false);  // 文本框不允许修改结果
        resultText.setFont(new Font("monospaced", Font.PLAIN, 18));    //设置结果文本框输入文字的字体、类型、大小
        History.setFont(new Font("monospaced", Font.PLAIN, 18));    //设置历史记录文本框输入文字的字体、类型、大小
        History.setBounds(290, 40, 250, 370);   // 设置文本框大小
        History.setAlignmentX(LEFT_ALIGNMENT);  // 文本框内容右对齐
        History.setEditable(false);     // 文本框不允许修改结果
        label.setBounds(300, 15, 100, 20);  //设置标签位置及大小
        jp2.setBounds(290, 40, 250, 370);   //设置面板窗口位置及大小
        jp2.setLayout(new GridLayout());
        JPanel jp1 = new JPanel();
        jp1.setBounds(20, 18, 255, 115);    //设置面板窗口位置及大小
        jp1.setLayout(new GridLayout());
        resultText.setLineWrap(true);   // 激活自动换行功能
        resultText.setWrapStyleWord(true);  // 激活断行不断字功能
        resultText.setSelectedTextColor(Color.RED);
        History.setLineWrap(true);  //自动换行
        History.setWrapStyleWord(true);
        History.setSelectedTextColor(Color.blue);
        gdt1.setViewportView(resultText);   //使滚动条显示出来
        gdt2.setViewportView(History);
        gdt1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);     //设置让垂直滚动条一直显示
        gdt2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);     //设置让垂直滚动条一直显示
        gdt2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);     //设置让水平滚动条一直显示
        jp1.add(gdt1);  //将滚动条添加入面板窗口中
        jp2.add(gdt2);
        this.add(jp1);  //将面板添加到总窗体中
        this.add(jp2);  //将面板添加到总窗体中
        this.setLayout(null);
        this.add(label);    // 新建“历史记录”标签

        // 放置按钮 x,y为按钮的横纵坐标
        int x = 20, y = 150;
        for (int i = 0; i < KEYS.length; i++) {
            keys[i] = new JButton();
            keys[i].setText(KEYS[i]);
            keys[i].setBounds(x, y, 60, 30);
            if (x < 215) {
                x += 65;
            } else {
                x = 20;
                y += 35;
            }
            this.add(keys[i]);
        }
        for (int i = 0; i < KEYS.length; i++)   // 每个按钮都注册事件监听器
        {
            keys[i].addActionListener(this);
        }
        this.setResizable(false);
        this.setBounds(500, 200, 567, 480);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setVisible(true);
    }

2.中缀转换为后缀

private String[] houzhui(String infix) {  //infix 中缀
        String s = "";// 用于承接多位数的字符串
        Stack<String> opStack = new Stack<String>();    // 操作符静态栈,对用户输入的操作符进行处理,用于存储运算符
        Stack<String> postQueue = new Stack<String>();   // 后缀表达式,为了将多位数存储为独立的字符串
        System.out.println("中缀:" + infix);
        for (int i = 0; i < infix.length(); i++)    // 遍历中缀表达式
        // indexof函数,返回字串首次出现的位置;charAt函数返回index位置处的字符;
        {
            if ("1234567890.".indexOf(infix.charAt(i)) >= 0) {    // 遇到数字字符直接入队
                //判断并记录多位操作数,比如,中缀表达式:234+4*2,我们扫描这个字符串的时候,s的作用相当于用来存储长度为3个字符的操作数:234
                s = "";// 作为承接字符,每次开始时都要清空
                for (; i < infix.length() && "0123456789.".indexOf(infix.charAt(i)) >= 0; i++) {
                    s = s + infix.charAt(i);
                }
                i--;   //避免跳过对非数字字符的处理
                postQueue.push(s);  // 数字字符直接加入后缀表达式
            } else if ("(".indexOf(infix.charAt(i)) >= 0) {   // 遇到左括号
                opStack.push(String.valueOf(infix.charAt(i)));   // 左括号入栈
            } else if (")".indexOf(infix.charAt(i)) >= 0) {   // 遇到右括号
                while (!opStack.peek().equals("(")) {    // 栈顶元素循环出栈,直到遇到左括号为止
                    postQueue.push(opStack.pop());
                }
                opStack.pop();     //删除左括号
            } else if ("*%/+-".indexOf(infix.charAt(i)) >= 0)   // 遇到运算符
            {
                if (opStack.empty() || "(".contains(opStack.peek())) {   // 若栈为空或栈顶元素为左括号则直接入栈
                    opStack.push(String.valueOf(infix.charAt(i)));
                } else {
                    // 当栈顶元素为高优先级或同级运算符时,让栈顶元素出栈进入后缀表达式后,直到符合规则后,当前运算符再入栈
                    boolean rule = ("*%/+-".contains(opStack.peek()) && "+-".indexOf(infix.charAt(i)) >= 0) || ("*%/".contains(opStack.peek()) && "*%/".indexOf(infix.charAt(i)) >= 0);
                    while (!opStack.empty() && rule) {
                        postQueue.push(opStack.peek());  //peek()方法:返回栈顶的元素但不移除它
                        opStack.pop();
                    }
                    opStack.push(String.valueOf(infix.charAt(i)));   // 当前元素入栈
                }
            }
        }
        while (!opStack.empty()) {// 遍历结束后将栈中剩余元素依次出栈进入后缀表达式
            postQueue.push(opStack.pop());
        }
        //将后缀表达式栈转换为字符串数组格式
        String[] suffix = new String[postQueue.size()];
        for (int i = postQueue.size() - 1; i >= 0; i--) {
            suffix[i] = postQueue.pop();
        }
        System.out.println("后缀:" + Arrays.toString(suffix.clone()));
        return suffix;
    }

3.计算后缀表达式,并计算出结果

public double Result(String[] suffix) {  //suffix 后缀
        Stack<String> Result = new Stack<>();// 顺序存储的栈,数据类型为字符串
        int i;
        for (i = 0; i < suffix.length; i++) {
            if ("1234567890.".indexOf(suffix[i].charAt(0)) >= 0) {  //遇到数字,直接入栈
                Result.push(suffix[i]);
            } else {    // 遇到运算符字符,将栈顶两个元素出栈计算并将结果返回栈顶
                double x, y, n = 0;
                x = Double.parseDouble(Result.pop());   // 顺序出栈两个数字字符串,并转换为double类型
                y = Double.parseDouble(Result.pop());
                switch (suffix[i]) {
                    case "*":
                        n = y * x;
                        break;
                    case "/":
                        if (x == 0) return 000000;
                        else n = y / x;
                        break;
                    case "%":
                        if (x == 0) return 000000;
                        else n = y % x;
                        break;
                    case "-":
                        n = y - x;
                        break;
                    case "+":
                        n = y + x;
                        break;
                }
                Result.push(String.valueOf(n)); // 将运算结果重新入栈
            }
        }

        System.out.println("return:" + Result.peek());
        return Double.parseDouble(Result.peek());   // 返回最终结果
    }

4.实现计算器的各种计算方法

public void actionPerformed(ActionEvent e) {
        String label = e.getActionCommand();    //获得事件源的标签
        if (Objects.equals(label, "AC"))    //清空按钮,消除显示屏文本框前面所有的输入和结果
        {
            input = "";
            resultText.setText("0.0");      //更新文本域的显示,显示初始值;
        } else if (Objects.equals(label, "sqrt")) {
            String m;
            double a = Double.parseDouble(input);
            if(input.isEmpty()) m="error!";     //加判断,先输入数字再输入开方符号才是合法的
            else m = String.valueOf(Math.sqrt(a));
            resultText.setText("sqrt" + "(" + input + ")" + "=" + m);       //使运算表达式显示在输入界面
            History.setText(History.getText() + resultText.getText() + "\n");       //获取输入界面的运算表达式并使其显示在历史记录文本框
            input = m;
        } else if (Objects.equals(label,"1/x")){
            String m;
            double a = Double.parseDouble(input);
            if(input.isEmpty()) m="error!";
            else m = String.valueOf(1.0/a);
            resultText.setText("1/" + input + "=" + m);
            History.setText(History.getText() + resultText.getText() + "\n");
            input = m;
        }else if (Objects.equals(label, "x^2")) {
            String m;
            Double a = Double.parseDouble(input);
            if(input.isEmpty()) m="error!";
            else m = String.valueOf(Math.pow(a,2));
            resultText.setText(input + "^2" + "=" + m);
            History.setText(History.getText() + resultText.getText() + "\n");
            input = m;
        } else if (Objects.equals(label, "%")) {
            String m;
            double a = Double.parseDouble(input);
            if(input.isEmpty()) m="error!";
            else m = String.valueOf(0.01*a);
            resultText.setText("%" + input + "=" + m);
            History.setText(History.getText() + resultText.getText() + "\n");
            input = m;
        } else if (Objects.equals(label, "=")) {
            if (input.isEmpty()) return;
            String[] s = houzhui(input);    //将中缀表达式转换为后缀表达式
            double result = Result(s);     //计算后缀表达式得出最终算式结果
            resultText.setText(input + "=" + result);
            History.setText(History.getText() + resultText.getText() + "\n");
        } else if (Objects.equals(label,"abs")) {
            String m;
            double a = Double.parseDouble(input);
            if(input.isEmpty()) m="error!";
            else m = String.valueOf(Math.abs(a));
            resultText.setText("abs(" + input + ")=" + m);
            History.setText(History.getText() + resultText.getText() + "\n");
            input = m;
        } else if (Objects.equals(label,"sin")) {
            String m;
            double a = Double.parseDouble(input);
            double radians = Math.toRadians(a);
            if(input.isEmpty()) m="error!";
            else {
                DecimalFormat df = new DecimalFormat("#.##");
                m = String.valueOf(Math.sin(radians));
            }
            resultText.setText("sin(" + input + "°)=" + m);
            History.setText(History.getText() + resultText.getText() + "\n");
            input = m;
        } else if (Objects.equals(label,"cos")) {
            String m;
            double a = Double.parseDouble(input);
            double radians = Math.toRadians(a);
            if(input.isEmpty()) m="error!";
            else {
                DecimalFormat df = new DecimalFormat("#.##");
                m = String.valueOf(Math.cos(radians));
            }
            resultText.setText("cos(" + input + "°)=" + m);
            History.setText(History.getText() + resultText.getText() + "\n");
            input = m;
        } else if (Objects.equals(label,"tan")) {
            String m;
            double a = Double.parseDouble(input);
            double radians = Math.toRadians(a);
            if(input.isEmpty()) m="error!";
            else {
                DecimalFormat df = new DecimalFormat("#.##");
                m = String.valueOf(Math.tan(radians));
            }
            resultText.setText("tan(" + input + "°)=" + m);
            History.setText(History.getText() + resultText.getText() + "\n");
            input = m;
        }else if (Objects.equals(label,"bin")) {
            String m;
            int a = Integer.parseInt(input);
            if(input.isEmpty()) m="error!";
            else m = Integer.toBinaryString(a);
            resultText.setText("("+input+")10" + "=" +"(" + m + ")2");
            History.setText(History.getText() + resultText.getText() + "\n");
            input = m;
        } else if (Objects.equals(label,"hex")) {
            String m;
            int a = Integer.parseInt(input);
            if(input.isEmpty()) m="error!";
            else m = Integer.toHexString(a);
            resultText.setText("("+input+")10" + "=" +"(" + m + ")16");
            History.setText(History.getText() + resultText.getText() + "\n");
            input = m;
        } else if (Objects.equals(label,"rou")){
            String m;
            double a = Double.parseDouble(input);
            if(input.isEmpty()) m="error!";
            else m = String.valueOf(Math.round(a));
            resultText.setText("round(" + input + ")" + "=" + m);
            History.setText(History.getText() + resultText.getText() + "\n");
            input = m;
        }else {
            if (Objects.equals(label, "e")) {
                String m = String.valueOf(2.71828);     //将e的值以字符串的形式传给m
                label = m;
            } else if (Objects.equals(label, "pi")) {
                String m = String.valueOf(3.14159);
                label = m;
            }
            input = input + label;
            resultText.setText(input);
        }
    }

六、使用git管理代码

仓库地址:LM的仓库: 记录 - Gitee.com


七、遇到的问题

1.无法打开GUI界面以及打开以后的界面按钮选项的排布很乱,导致超出窗口

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值