第一次作业:计算器软件

发布时间 2023-10-13 20:38:37作者: 任璀梅

可实现加、减、乘、除、开平方的计算器软件的实验设计

1、加、减、乘、除、开平方代码:

#include <stdio.h>
#include <math.h>

// 牛顿迭代法计算平方根
double sqrt_newton(double x) {
double guess = x / 2.0; // 初始猜测值为x的一半
double delta = 0.000001; // 误差范围

while (fabs(guess * guess - x) > delta) {
guess = (guess + x / guess) / 2.0; // 更新猜测值
}

return guess;
}

int main() {
int choice;
double num1, num2;

printf("选择操作:\n");
printf("1. 加法\n");
printf("2. 减法\n");
printf("3. 乘法\n");
printf("4. 除法\n");
printf("5. 算术开方\n");
printf("请选择:");
scanf("%d", &choice);

switch (choice) {
case 1:
printf("请输入两个数字:");
scanf("%lf %lf", &num1, &num2);
printf("结果:%lf\n", num1 + num2);
break;
case 2:
printf("请输入两个数字:");
scanf("%lf %lf", &num1, &num2);
printf("结果:%lf\n", num1 - num2);
break;
case 3:
printf("请输入两个数字:");
scanf("%lf %lf", &num1, &num2);
printf("结果:%lf\n", num1 * num2);
break;
case 4:
printf("请输入两个数字:");
scanf("%lf %lf", &num1, &num2);
if (num2 != 0) {
printf("结果:%lf\n", num1 / num2);
} else {
printf("除数不能为0!\n");
}
break;
case 5:
printf("请输入一个数字:");
scanf("%lf", &num1);
if (num1 >= 0) {
printf("结果:%lf\n", sqrt_newton(num1));
} else {
printf("输入的数字不能小于0!\n");
}
break;
default:
printf("无效的选择!\n");
}

return 0;
}

 

2.Javaswing来实现一个简单计算器,主要内容为图形用户界面UI的实现以及运算表达式核心算法的设计编写。程序运行环境为Windows10 ,编译环境为IntelliJ IDEA  2023.2.2

Visio设计计算器软件中所涉及的流程图:

 

完整代码如下:

import javax.swing.*;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.util.*;

import java.util.stream.Collectors;

 

public class Calculator extends JFrame implements ActionListener {

    Calculator() {

        init();

    }

 

    /**

     * 定义按钮

     */

    private JTextField textField1;

    private JTextArea textField2;

    private JButton buttonzuo;//(

    private JButton buttonyou;//)

    private JButton buttonC;//c

    private JButton buttonCE;//CE

    private JButton buttondele;//<- 删除

    private JButton buttonDiv;//÷

    private JButton button7;//7

    private JButton button8;//8

    private JButton button9;//9

    private JButton buttonAdd;//+

    private JButton button4;//4

    private JButton button5;//5

    private JButton button6;//6

    private JButton buttonSub;//-

    private JButton button1;//1

    private JButton button2;//2

    private JButton button3;//3

    private JButton buttonMul;//x

    private JButton buttonequl;//=

    private JButton button0;//0

    private JButton buttonPoint;//.

 

    public void init() {

        JFrame frame = new JFrame("The Calculator Of 崔登辉");                  //普通窗口顶层容器   创建标题为“计算器”;

        frame.setLayout(null);                                                   //设置使用特定的布局管理器;

        //单选项按钮

        //按键的排版以及设计需要提前考虑整体的布局合理性,不可出现按键重叠;为了保证美观又需要考虑排版整齐;

        //放置数字0

        button0 = new JButton("0");                                         //注:在给按键命名时要根据按键的大小,否则按键上的标注无法完全显示;

        button0.setBounds(100, 400, 110, 50);

        frame.add(button0);

        //放置数字1

        button1 = new JButton("1");

        button1.setBounds(40, 340, 50, 50);

        frame.add(button1);

        //放置数字2

        button2 = new JButton("2");

        button2.setBounds(100, 340, 50, 50);

        frame.add(button2);

        //放置数字3

        button3 = new JButton("3");

        button3.setBounds(160, 340, 50, 50);

        frame.add(button3);

        //放置数字4

        button4 = new JButton("4");

        button4.setBounds(40, 280, 50, 50);

        frame.add(button4);

        //放置数字5

        button5 = new JButton("5");

        button5.setBounds(100, 280, 50, 50);

        frame.add(button5);

        //放置数字6

        button6 = new JButton("6");

        button6.setBounds(160, 280, 50, 50);

        frame.add(button6);

        //放置数字7

        button7 = new JButton("7");

        button7.setBounds(40, 220, 50, 50);

        frame.add(button7);

        //放置数字8

        button8 = new JButton("8");

        button8.setBounds(100, 220, 50, 50);

        frame.add(button8);

        //放置数字9

        button9 = new JButton("9");

        button9.setBounds(160, 220, 50, 50);

        frame.add(button9);

        //放置 .

        buttonPoint = new JButton(".");                                                   //text:为自动生成的参数的解释词

        buttonPoint.setBounds(40, 400, 50, 50);                            //自动补齐的参数解释词

        frame.add(buttonPoint);

        //放置 +

        buttonAdd = new JButton("+");

        buttonAdd.setBounds(220, 400, 50, 50);

        frame.add(buttonAdd);

        //放置 -

        buttonSub = new JButton("-");

        buttonSub.setBounds(220, 340, 50, 50);

        frame.add(buttonSub);

        //放置 *

        buttonMul = new JButton("*");

        buttonMul.setBounds(220, 280, 50, 50);

        frame.add(buttonMul);

        //放置 /

        buttonDiv = new JButton("/");

        buttonDiv.setBounds(220, 220, 50, 50);

        frame.add(buttonDiv);

        //放置 =

        buttonequl = new JButton("=");

        buttonequl.setBounds(280, 340, 110, 110);

        frame.add(buttonequl);

        //退位键

        buttondele = new JButton("B");

        buttondele.setBounds(280, 220, 110, 110);

        frame.add(buttondele);

        //放置左括号(

        buttonzuo = new JButton("(");

        buttonzuo.setBounds(40, 160, 80, 50);

        frame.add(buttonzuo);

        //放置右括号)

        buttonyou = new JButton(")");

        buttonyou.setBounds(130, 160, 80, 50);

        frame.add(buttonyou);

        //放置C  消除所有输入

        buttonC = new JButton("C");

        buttonC.setBounds(220, 160, 80, 50);

        frame.add(buttonC);

        //放置CE 消除当前输入

        buttonCE = new JButton("CE");

        buttonCE.setBounds(310, 160, 80, 50);

        frame.add(buttonCE);

        //添加表达式文本框 用以输入计算公式

        textField1 = new JTextField();           //文本框

        textField1.setBounds(40, 20, 350, 60);

        frame.add(textField1);

        textField2 = new JTextArea();

        textField2.setBounds(400, 20, 280, 430);

        frame.add(textField2);

 

 

        textField1.addActionListener(this);

        buttonzuo.addActionListener(this);

        buttonyou.addActionListener(this);

        buttonC.addActionListener(this);

        buttonCE.addActionListener(this);

        buttondele.addActionListener(this);

        buttonDiv.addActionListener(this);

        button7.addActionListener(this);

        button8.addActionListener(this);

        button9.addActionListener(this);

        buttonAdd.addActionListener(this);

        button4.addActionListener(this);

        button5.addActionListener(this);

        button6.addActionListener(this);

        buttonSub.addActionListener(this);

        button1.addActionListener(this);

        button2.addActionListener(this);

        button3.addActionListener(this);

        buttonMul.addActionListener(this);

        buttonequl.addActionListener(this);

        button0.addActionListener(this);

        buttonPoint.addActionListener(this);

 

        frame.setBounds(0, 0, 700, 520);       //设置整个图形窗口的大小;(通过窗口名调用)

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE),当点击窗口的关闭按钮时退出程序(没有这一句,程序不会退出)

        frame.setVisible(true);

    }

 

    String str = null;

    int pointbook = 0;

    int equalbook = 0;

    int zuonum = 0;

    int younum = 0;

    int equnum = 0;

 

 

    public void actionPerformed(ActionEvent e) {

        if (equnum == 1) {

            textField1.setText("0");

            equnum = 0;

        }

        //按0

        if (e.getSource().equals(button0)) {

            str = textField1.getText();

            if (str.length() > 16 || str.equals("0") || equalbook == 1) {

 

            } else {

                textField1.setText(str + "0");

            }

        }

        //按1

        if (e.getSource().equals(button1)) {

            str = textField1.getText();

            if (str.length() > 16 || equalbook == 1) {

 

            } else if (str.equals("0") || str.equals("")) {

                textField1.setText("1");

            } else {

                textField1.setText(str + "1");

            }

        }

        //当按钮为2时

        if (e.getSource().equals(button2)) {

            str = textField1.getText();

            if (str.length() > 16 || equalbook == 1) {

            } else if (str.equals("0") || str.equals("")) {

                textField1.setText("2");

            } else {

                textField1.setText(str + "2");

            }

        }

        //当按钮为3时

        if (e.getSource().equals(button3)) {

            str = textField1.getText();

            if (str.length() > 16 || equalbook == 1) {

            } else if (str.equals("0") || str.equals("")) {

                textField1.setText("3");

            } else {

                textField1.setText(str + "3");

            }

        }

        //当按钮为4时

        if (e.getSource().equals(button4)) {

            str = textField1.getText();

            if (str.length() > 16 || equalbook == 1) {

            } else if (str.equals("0") || str.equals("")) {

                textField1.setText("4");

            } else {

                textField1.setText(str + "4");

            }

        }

        //当按钮为5时

        if (e.getSource().equals(button5)) {

            str = textField1.getText();

            if (str.length() > 16 || equalbook == 1) {

            } else if (str.equals("0") || str.equals("")) {

                textField1.setText("5");

            } else {

                textField1.setText(str + "5");

            }

        }

        //当按钮为6时

        if (e.getSource().equals(button6)) {

            str = textField1.getText();

            if (str.length() > 16 || equalbook == 1) {

            } else if (str.equals("0") || str.equals("")) {

                textField1.setText("6");

            } else {

                textField1.setText(str + "6");

            }

        }

        //当按钮为7时

        if (e.getSource().equals(button7)) {

            str = textField1.getText();

            if (str.length() > 16 || equalbook == 1) {

            } else if (str.equals("0") || str.equals("")) {

                textField1.setText("7");

            } else {

                textField1.setText(str + "7");

            }

        }

        //当按钮为8时

        if (e.getSource().equals(button8)) {

            str = textField1.getText();

            if (str.length() > 16 || equalbook == 1) {

            } else if (str.equals("0") || str.equals("")) {

                textField1.setText("8");

            } else {

                textField1.setText(str + "8");

            }

        }

        //当按钮为9时

        if (e.getSource().equals(button9)) {

            str = textField1.getText();

            if (str.length() > 16 || equalbook == 1) {

            } else if (str.equals("0") || str.equals("")) {

                textField1.setText("9");

            } else {

                textField1.setText(str + "9");

            }

        }

        //当按钮为小数点时

        if (e.getSource().equals(buttonPoint)) {

            str = textField1.getText();

            if (str.length() > 15 || equalbook == 1) {                   //小数点位于操作数的最后一位不执行操作;

            }

            if (pointbook == 0) {                                    //一个操作数仅能有一个小数点,若已经有小数点则不再添加小数点;

                textField1.setText(str + ".");

                pointbook = 1;                                    //小数点判断位置1;

            }

        }

        //每次输入都是一个数字+运算符,一起从数字文本框转而输入到表达式文本框中;

        //当按钮为加号时

        if (e.getSource().equals(buttonAdd)) {

            str = textField1.getText();                              //获取运算符前一个操作数;

            char ch1[] = str.toCharArray();                        //把第一操作数连同+号 进行字符串转字符数组的操作 赋予ch1;

            int length1 = str.length() - 1;                        //length1获取除+号外的第一操作数的位数;

            if ((length1 == -1 || ch1[length1] != ')') && (str.equals("0") || str.equals("") || ch1[length1] == '.' || ch1[length1] == '+' || ch1[length1] == '-' || ch1[length1] == '*' || ch1[length1] == '/' || ch1[length1] == '(' || ch1[length1] == ')')) {

                //当数字为空或为0(操作无意义);或数字的最后一位是小数点(未输入完毕或输入出错,等待)

            } else {

                textField1.setText(str + "+");   //合并现有表达式和新增表达式

                // 这里解释以下为什么s没有提取到数字框里的符号,因为输入符号时并没有更新数字框,而是直接执行一系列操作,数字框从未出现过运算符;

            }

            pointbook = 0;

        }

        //当按钮为减号时

        if (e.getSource().equals(buttonSub)) {

            str = textField1.getText();

            char ch1[] = str.toCharArray();

            int length1 = str.length() - 1;

            if ((length1 == -1 || ch1[length1] != ')') && (ch1[length1] == '.' || ch1[length1] == '+' || ch1[length1] == '-' || ch1[length1] == '*' || ch1[length1] == '/' || ch1[length1] == '(' || ch1[length1] == ')')) {

            } else {

                textField1.setText(str + "-");

            }

            pointbook = 0;

        }

        //当按钮为乘号时

        if (e.getSource().equals(buttonMul)) {

            str = textField1.getText();

            char ch1[] = str.toCharArray();

            int length1 = str.length() - 1;

            if ((length1 == -1 || ch1[length1] != ')') && (str.equals("0") || str.equals("") || ch1[length1] == '.' || ch1[length1] == '+' || ch1[length1] == '-' || ch1[length1] == '*' || ch1[length1] == '/' || ch1[length1] == '(' || ch1[length1] == ')')) {

            } else {

                textField1.setText(str + "*");

            }

            pointbook = 0;

        }

        //当按钮为除号时

        if (e.getSource().equals(buttonDiv)) {

            str = textField1.getText();

            char ch1[] = str.toCharArray();

            int length1 = str.length() - 1;

            if ((length1 == -1 || ch1[length1] != ')') && (str.equals("0") || str.equals("") || ch1[length1] == '.' || ch1[length1] == '+' || ch1[length1] == '-' || ch1[length1] == '*' || ch1[length1] == '/' || ch1[length1] == '(' || ch1[length1] == ')')) {

            } else {

                textField1.setText(str + "/");

            }

            pointbook = 0;

        }

        //当按钮为左括号时

        if (e.getSource().equals(buttonzuo)) {

            str = textField1.getText();

            char ch[] = str.toCharArray();

            int length = str.length() - 1;

            if (length == -1 || ch[length] == '+' || ch[length] == '-' || ch[length] == '*' || ch[length] == '/') {

                //括号左边是否有数或符号类别的判断;

                textField1.setText(str + '(');     //满足条件则加入左括号;

                zuonum++;                                            //左括号数加一标记;

            }

            if (length == -1 || ch[length] == '+' || ch[length] == '-' || ch[length] == '*' || ch[length] == '/')

                pointbook = 0;

            if (length == 0 || ch[length] == 0) {

                textField1.setText("(");

                zuonum++;

            }

        }

        //当按钮为右括号时;

        if (e.getSource().equals(buttonyou)) {

            str = textField1.getText();

            char ch[] = str.toCharArray();

            int length = str.length() - 1;

            if (Character.isDigit(ch[length]) && zuonum > younum) {      //只有前面是数字的时候且左括号的数量大于右括号的数量的时候才能加右括号;

                younum++;                                                 //右括号数加一标记;

                textField1.setText(str + ')');

            }

            pointbook = 0;

        }

        //当按下C键时;

        if (e.getSource().equals(buttonC)) {

            textField1.setText("0");                  //置当前数字框为0;

            zuonum = 0;                              //当一次计算完成之后,只有按CE按钮才能进行新的计算,因为要清除所有标志位否则会影响下一次操作;

            younum = 0;

            pointbook = 0;

            equalbook = 0;

            textField2.setText(" ");

        }

        //当按钮为CE时,

        if (e.getSource().equals(buttonCE)) {

            textField1.setText("0");                       //清除当前数字框中内容;

            pointbook = 0;                                 //更新小数点状态为0;

        }

        //当按下B时,

        if (e.getSource().equals(buttondele)) {

            str = textField1.getText();

            char []nums=str.toCharArray();

            if (nums[str.length()-1]=='('){

                zuonum--;

            }

            str = str.substring(0, str.length() - 1);

            textField1.setText(str);

        }

        //当按下=时,

        if (e.getSource().equals(buttonequl)) {

            str = textField1.getText();

            if (zuonum != younum) {

                textField1.setText("关系式错误。");

            } else {

                ans(str);

            }

            String s = str + "=" + textField1.getText();

            textField2.setText(s + "\r\n" + textField2.getText());                //将表达式存放在历史记录里。

            equnum = 1;

        }

    }

 

 

    /**

     * 提前将 符号的优先级定义好

     */

    private static final Map<Character, Integer> basic = new HashMap<Character, Integer>();

 

    static {

        basic.put('-', 1);

        basic.put('+', 1);

        basic.put('*', 2);

        basic.put('/', 2);

        basic.put('(', 0);//在运算中  ()的优先级最高,但是此处因程序中需要 故设置为0

    }

 

 

    public void ans(String str) {

        String a = toSuffix(str);//传入 一串 算数公式

        textField1.setText(dealEquation(a));

 

    }

 

    /**

     

     */

    public String toSuffix(String infix) {

        List<String> queue = new ArrayList<String>();                                    //定义队列  用于存储 数字  以及最后的  后缀表达式

        List<Character> stack = new ArrayList<Character>();                             //定义栈    用于存储  运算符  最后stack中会被 弹空

 

        char[] charArr = infix.trim().toCharArray();                                    //字符数组  用于拆分数字或符号

        String standard = "*/+-()";                                                        //判定标准 将表达式中会出现的运算符写出来

        char ch = '&';                                                                    //在循环中用来保存 字符数组的当前循环变量的  这里仅仅是初始化一个值  没有意义

        int len = 0;                                                                    //用于记录字符长度 【例如100*2,则记录的len为3 到时候截取字符串的前三位就是数字】

        for (int i = 0; i < charArr.length; i++) {                                        //开始迭代

 

            ch = charArr[i];                                                            //保存当前迭代变量

            if (Character.isDigit(ch)) {                                                    //如果当前变量为 数字

                len++;

            } else if (Character.isLetter(ch)) {                                            //如果当前变量为  字母

                len++;

            } else if (ch == '.') {                                                        //如果当前变量为  .  会出现在小数里面

                len++;

            } else if (Character.isSpaceChar(ch)) {                                        //如果当前变量为 空格  支持表达式中有空格出现

                if (len > 0) {                                                            //若为空格 代表 一段结束 ,就可以往队列中  存入了  【例如100 * 2  100后面有空格 就可以将空格之前的存入队列了】

                    queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i)));    //往 队列存入 截取的 字符串

                    len = 0;                                                            //长度置空

                }

                continue;                                                                //如果空格出现,则一段结束  跳出本次循环

            } else if (standard.indexOf(ch) != -1) {                                        //如果是上面标准中的 任意一个符号

                if (len > 0) {                                                            //长度也有

                    queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i)));    //说明符号之前的可以截取下来做数字

                    len = 0;                                                            //长度置空

                }

                if (ch == '(') {                                                            //如果是左括号

                    stack.add(ch);                                                        //将左括号 放入栈中

                    continue;                                                            //跳出本次循环  继续找下一个位置

                }

                if (!stack.isEmpty()) {                                                    //如果栈不为empty

                    int size = stack.size() - 1;                                        //获取栈的大小-1  即代表栈最后一个元素的下标

                    boolean flag = false;                                                //设置标志位

                    while (size >= 0 && ch == ')' && stack.get(size) != '(') {            //若当前ch为右括号,则 栈里元素从栈顶一直弹出,直到弹出到 左括号

                        queue.add(String.valueOf(stack.remove(size)));                    //注意此处条件:ch并未入栈,所以并未插入队列中;同样直到找到左括号的时候,循环结束了,所以左括号也不会放入队列中【也就是:后缀表达式中不会出现括号】

                        size--;                                                            //size-- 保证下标永远在栈最后一个元素【栈中概念:指针永远指在栈顶元素】

                        flag = true;                                                    //设置标志位为true  表明一直在取()中的元素

                    }

                    while (size >= 0 && !flag && basic.get(stack.get(size)) >= basic.get(ch)) {    //若取得不是()内的元素,并且当前栈顶元素的优先级>=对比元素 那就出栈插入队列

                        queue.add(String.valueOf(stack.remove(size)));                    //同样  此处也是remove()方法,既能得到要获取的元素,也能将栈中元素移除掉

                        size--;

                    }

                }

                if (ch != ')') {                                                            //若当前元素不是右括号

                    stack.add(ch);                                                        //就要保证这个符号 入栈

                } else {                                                                //否则就要出栈 栈内符号

                    stack.remove(stack.size() - 1);

                }

            }

            if (i == charArr.length - 1) {                                                //如果已经走到了  中缀表达式的最后一位

                if (len > 0) {                                                            //如果len>0  就截取数字

                    queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len + 1, i + 1)));

                }

                int size = stack.size() - 1;                                            //size表示栈内最后一个元素下标

                while (size >= 0) {                                                        //一直将栈内  符号全部出栈 并且加入队列中  【最终的后缀表达式是存放在队列中的,而栈内最后会被弹空】

                    queue.add(String.valueOf(stack.remove(size)));

                    size--;

                }

            }

 

        }

        return queue.stream().collect(Collectors.joining(","));                            //将队列中元素以,分割 返回字符串

    }

 

 

    /**

     * 将 后缀表达式 进行  运算 计算出结果

     *

     * @param equation

     * @return

     */

    public String dealEquation(String equation) {

        String[] arr = equation.split(",");                                    //根据, 拆分字符串

        List<String> list = new ArrayList<String>();                            //用于计算时  存储运算过程的集合【例如list中当前放置  100   20  5  /  则取出20/5 最终将结果4存入list   此时list中结果为  100  4 】

 

 

        for (int i = 0; i < arr.length; i++) {                                    //此处就是上面说的运算过程, 因为list.remove的缘故,所以取出最后一个数个最后两个数  都是size-2

            int size = list.size();

            switch (arr[i]) {

                case "+":

                    double a = Double.parseDouble(list.remove(size - 2)) + Double.parseDouble(list.remove(size - 2));

                    list.add(String.valueOf(a));

                    break;

                case "-":

                    double b = Double.parseDouble(list.remove(size - 2)) - Double.parseDouble(list.remove(size - 2));

                    list.add(String.valueOf(b));

                    break;

                case "*":

                    double c = Double.parseDouble(list.remove(size - 2)) * Double.parseDouble(list.remove(size - 2));

                    list.add(String.valueOf(c));

                    break;

                case "/":

                    double d = Double.parseDouble(list.remove(size - 2)) / Double.parseDouble(list.remove(size - 2));

                    list.add(String.valueOf(d));

                    break;

                default:

                    list.add(arr[i]);

                    break;                                    //如果是数字  直接放进list中

            }

        }

        return list.size() == 1 ? list.get(0) : "运算失败";                    //最终list中仅有一个结果,否则就是算错了

    }

 

    public static void main(String[] args) {

        Calculator calculator = new Calculator();

    }

}

结果测试:

 

 

分析: 

1、可实现基本四则运算及开方运算。
2、运算表达式可显示于输入界面并保存于历史记录栏
3、不足之处:进行开方运算时其保存在历史记录中的表达式会出现两个等号及两个结果。