四则运算程序(java基于控制台)

一、题目描述:

1. 使用 -n 参数控制生成题目的个数,例如

Myapp.exe -n 10 -o Exercise.txt

将生成10个题目。

2. 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如

Myapp.exe -r 10

将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。

3. 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。

4. 每道题目中出现的运算符个数不超过3个。

5. 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。3+(2+1)和1+2+3这两个题目是重复的,由于

+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。

生成的题目存入执行程序的当前目录下的Exercises.txt文件,格式如下:

1. 四则运算题目1

2. 四则运算题目2

……

        其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。
    6. 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:
            1. 答案1
            2. 答案2

        特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。
    7. 程序应能支持一万道题目的生成。
    8. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,并会输出所有题目中重复的题目,输入参数如下:
         Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt -o Grade.txt

        统计结果输出到文件Grade.txt,格式如下:

        Correct: 5 (1, 3, 5, 7, 9)
        Wrong: 5 (2, 4, 6, 8, 10)
        Repeat:2
        RepeatDetail:
        (1)   2,45+32  Repeat 3,32+45
        (2)   5,3+(2+1)  Repeat 7,1+2+3

二、分析设计

1.生成随机表达式

需要生成随机数(整数,分数,带分数)的函数,随机运算符的函数,随机添加括号函数,采用String拼接生成随机表达式。

2.表达式处理计算

将中缀表达式转换为后缀表达式,对后缀表达式进行分割处理,通过栈操作进行运算,由于存在分数和带分数,需通过自定义四则运算法则进行计算,具体为同化成分数进行运算,完成后需约分。

3.表达式查重

先通过读取答案文档,扫描相同答案的表达式进行判断,可提高效率,接着再将相同答案的中缀表达式转换成后缀表达式,判断所有元素是否相等。此方法效率较高,但存在局限性。由于本人并不是通过二叉树处理表达式,再使用二叉树显得 很繁琐,且效率不高。

4.输出至文档

需要输出的文档有表达式Exercises.txt,答案Answers.txt,成绩及查重结果Grade.txt。

三、功能实现

    1.主程序Main.java
        主要代码:
    System.out.println("---------------四则运算程序---------------");
    System.out.println("-n:生成题目个数");
    System.out.println("-r:参数数值范围");
    System.out.println("-g:查看测试结果");
    System.out.println("Do:执行程序");
    System.out.println("请输入指令:");
    Scanner in =new Scanner(System.in);
    while(in.hasNext()){
        switch(in.next()){
            case "-n" :
                System.out.println("请输入要生成的题目个数:");
                n=in.nextInt();
                break;
            case "-r":
                System.out.println("请输入运算数的数值范围:");
                m=in.nextInt();
                break;
            case "-g":
                fo.FileC(file2, file3, file4);        //答案和做题文档对比,结果写入Grade文档
                break;
            case "Do":
                for(int i=0;i<n;i++){
                    String s=ex.CreatExp(n,m),fstr;   //生成随机表达式并求解
                    String rus=its.suffixToArithmetic(its.infixToSuffix(s));

                    fstr=i+1+":"+s+"\r\n";
                    fo.FileW(file1, fstr);            //表达式写入文档

                    fstr=i+1+":"+rus+"\r\n";
                    fo.FileW(file2, fstr);            //答案写入文档
                }
                break;
            default:
                System.out.println("无效指令!");
                break;
        }
        System.out.println("请输入指令:");   

    2.随机表达式生成
        主要代码:
        /*随机生成表达式*/
    public String CreatExp(int n ,int m){
        String exp=CreatNum(m);                          //随机操作数
        Random rd=new Random();
        int t=rd.nextInt(2);
        boolean flag=false;                              //是否生成括号
        if(t>0)
            flag=Creatkh();
        for(int i=0;i<=t;i++){                           //生成String类型中缀表达式
            if(flag==true){
                if(i==0){
                    exp=exp+CreatChar()+"("+CreatNum(m);
                }else
                {
                    exp=exp+CreatChar()+CreatNum(m)+")";
                }
                    }else{
                exp=exp+CreatChar()+CreatNum(m);
            }
        }
        return exp;
    }

    /*随机生成操作数*/
    public String CreatNum(int m){
        String s="";
        Random rd=new Random();
        switch(rd.nextInt(2)){                            //随机类型:整数,分数
            case 0:
                s=Integer.toString(rd.nextInt(m-1)+1);    //整数
                break;
            case 1:                                       //分数
                int a,b;
                a=rd.nextInt(m-1)+1;
                b=rd.nextInt(m-2)+2;
                s=Dating(a,b);                            //分数约分处理
                break;
        }
        return s;
    }

    /*随机生成运算符*/
    public String CreatChar(){
        String s="";
        Random rd=new Random();
        switch(rd.nextInt(4)){
            case 0:s="+";break;
            case 1:s="-";break;
            case 2:s="*";break;
            case 3:s="÷";break;
        }
        return s;
    }

    /*分数进行约分*/
    public String Dating(int a,int b){
        String s="";
        int gongyinshu=1,c;
        c=a/b;
        a=a%b;
        if(c<0){                                   //若带分数已为负数,这分数不用带负号
            a=a*-1;
        }
        for (int i = 1; i <= a; i++) {             //求最小公约数
            if (a % i == 0 && b % i == 0) {
                gongyinshu = i;
            }
        }
        a=a/gongyinshu;                            //生成最简分数
        b=b/gongyinshu;
        if(a==0){
            s=Integer.toString(c);
        }else if(c==0){
            s=Integer.toString(a)+"/"+Integer.toString(b);
        }else{
            s=Integer.toString(c)+"‘"+Integer.toString(a)+"/"+Integer.toString(b);
        }
        return s;
    }

    /*随机是否生成括号*/
    public boolean Creatkh(){
        boolean flag=false;
        Random rd=new Random();
        if(rd.nextInt(3)<1)                        //生成扩号的概率为1/3
            flag=true;
        return flag;
    }

    3.表达式处理
        主要代码:
        /*中缀表达式转后缀表达式*/
        public String infixToSuffix(String exp) {
            Stack<Character> s = new Stack<Character>();                // 创建操作符堆栈
            String suffix = "";                                         // 要输出的后缀表达式字符串
            int length = exp.length();                                  // 输入的中缀表达式的长度
            for (int i = 0; i < length; i++) {
                 char temp;
                 char ch = exp.charAt(i);                               // 获取该中缀表达式的每一个字符并进行判断
                 switch (ch) {
                    case ‘(‘:
                        s.push(ch);
                        break;
                    case ‘+‘:                              // 碰到‘+‘ ‘-‘,将栈中的所有运算符全部弹出去,直至碰到左括号为止,输出到队列中去
                    case ‘-‘:
                        suffix += " ";
                        while (s.size() != 0) {
                            temp = s.pop();
                            if (temp == ‘(‘) {
                                s.push(‘(‘);
                                break;
                            }
                            suffix += temp;
                            suffix += " ";
                        }
                        s.push(ch);
                        break;
                    case ‘*‘:                               // 如果是乘号或者除号,则弹出所有序列,直到碰到加好、减号、左括号为止,最后将该操作符压入堆栈
                    case ‘÷‘:
                        suffix += " ";
                        while (s.size() != 0) {
                            temp = s.pop();
                            if (temp == ‘+‘ || temp == ‘-‘ || temp == ‘(‘) {
                                 s.push(temp);
                                 break;
                            } else {
                                 suffix += temp;
                                 suffix += " ";
                           }
                        }
                        s.push(ch);
                        break;
                    case ‘)‘:
                         while (!s.isEmpty()) {
                            temp = s.pop();
                            if (temp == ‘(‘) {
                                     break;
                            } else {
                                    suffix += " ";
                                    suffix += temp;
                            }
                         }
                         break;
                    default:
                         suffix += ch;
                         break;
                 }
            }
            while (s.size() != 0) {                            // 如果堆栈不为空,则把剩余运算符一次弹出,送至输出序列
                    suffix += " ";
                        suffix += s.pop();
             }
            return suffix;
         }

         /*计算后缀表达式*/
         public String suffixToArithmetic(String exp) {
             String[] strings = exp.split(" ");                  //按空格分解字符串
             Stack<String> stack = new Stack<String>();          //操作数栈
             for (int i = 0; i < strings.length; i++) {
                 if(strings[i].equals("+")||strings[i].equals("-")||strings[i].equals("*")||strings[i].equals("÷")){
                     String y=stack.pop();                        //读取到运算符,提取栈顶的两个操作数,先出的操作数为运算符后的数
                     String x=stack.pop();
                     String rus=calculate(x, y, strings[i]);      //调用自定义的四则运算法则
                     stack.push(rus);
                     if(rus.equals("无解"))                       //除数为0返回无解
                     return rus;
                     }else{
                         stack.push(strings[i]);
                 }
             }
             return stack.pop();
         }

        /*自定义四则运算法则*/
         public String calculate(String x, String y, String ch) {
         }
         注:四则运算过程代码较多,不展示。

    4.文件操作及表达式查重代码不展示

四、结果展示

命令选择:

表达式文档:

答案文档:

答题文档:

成绩文档:

一万道题测试:

五、实验小结

此次编程要点在于表达式的处理,重点是对分数,带分数的处理,具体解决方法是将其每个部分的整数提取出来,存于几个参数中,通过参数间的转化运算达到分数的计算,从而实现表达式的计算。过程中遇到挺多小问题,例如除数为0,6÷(3-3) ,解决方法为计算除法时,进行判断,如果除数为0直接返回结果“无解”。

六 、PSP表

    PSP2.1  Personal Software Process Stages  Time Senior Student  Time
    Planning       计划                           2                   2
    Estimate    估计这个任务需要多少时间             48                  36
    Development  开发                            40                  36
    Analysis      需求分析 (包括学习新技术)          2                   1
    Design Spec   生成设计文档                     1                    1
    Design Review  设计复审                        2                        1
    Coding Standard 代码规范                  0                    0
    Design      具体设计                           3                      4
    Coding      具体编码                  27                    22
    Code Review  代码复审                          2                      1
    Test       测试(自我测试,修改代码,提交修改        2                     4
    Reporting   报告                             1                   2

七、源代码

码云项目地址:https://gitee.com/liangs96_master/FourOperations

原文地址:https://www.cnblogs.com/liangs96/p/8684291.html

时间: 2024-08-28 07:33:54

四则运算程序(java基于控制台)的相关文章

基于控制台的四则运算

一.题目要求:完成一个基于控制台的四则运算程序,实现一个自动生成小学四则运算题目的命令行程序 满足以下需求: 1.除了整数以外,还要支持真分数的四则运算,真分数的运算,例如:1/6 + 1/8 = 7/24 2.运算符为 +, ?, ×, ÷ 3.并且要求能处理用户的输入,并判断对错,打分统计正确率. 4.要求能处理用户输入的真分数, 如 1/2, 5/12 等 5.使用 -n 参数控制生成题目的个数,例如执行下面命令将生成10个题目 Myapp.exe -n 10 二.需求分析 能够自动生成四

四则运算程序的测试与封装

程序原型:之前的小学生四则运算程序 编程语言:java 测试代码如下: 1 package SuanFa; 2 3 import static org.junit.Assert.*; 4 5 import org.junit.Test; 6 7 public class CoreTest { 8 9 @Test 10 public void testJia() { 11 Core core = new Core(); 12 double a = core.jia(9, -3); 13 Syste

四则运算练习器(基于控制台)

题目链接:http://www.cnblogs.com/HQL0301/p/7502315.htm 源码连接:https://gitee.com/a1234321/four_operations/tree/master 一.需求分析 ?可以根据输入的题数和数值范围自动生成四则运算表达式. ?表达式包括"+ - * /"这四种运算符. ?可以进行分数的运算,如果题目中出现假分数,则转换成真分数. ?对题目答案进行批改对错,给出正确率. 二.功能设计 (1)基本功能 1.输入参数n,程序生

个人作业1——四则运算题目生成程序(基于控制台)

No.1 四则运算题目生成程序(基于控制台) 程序代码 需求分析: 能够根据用户自身对题目数量的需求自动生成一定数量的包含分数的四则运算题目的命令行程序. 功能设计: 除了整数以外,还要支持真分数的四则运算,真分数的运算 并且要求能处理用户的输入,并判断对错,打分统计正确率 要求能处理用户输入的真分数 使用 -n 参数控制生成题目的个数 设计实现: 程序是用c++实现的,主要有四个函数,主函数随机生成整数或者分数算法,divisor(int i, int j)计算最大公约数,zs为计算整数算法,

Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用

目录: 一.什么是Thrift? 1) Thrift内部框架一瞥 2) 支持的数据传输格式.数据传输方式和服务模型 3) Thrift IDL 二.Thrift的官方网站在哪里? 三.在哪里下载?需要哪些组件的支持? 四.如何安装? 五.Golang.Java.Python.PHP之间通过Thrift实现跨语言调用 1) Golang 客户端和服务端的实现及交互 2) python 客户端的实现与golang 服务端的交互 3) php 客户端的实现与golang 服务端的交互 4) java

JAVA基于AE调用GP实现泰森多边形

public void CreatVoronoi(){ try { GeoProcessor gp=new GeoProcessor(); gp.setOverwriteOutput(true); CreateThiessenPolygons createThiessen=new CreateThiessenPolygons(); createThiessen.setInFeatures("F:/db/pts.shp") createThiessen.setOutFeatureClas

基于控制台实现贪吃蛇游戏

1).引言 学习编程,我个人觉得最好的办法就是根据自己的水平不断的给自己设定一个小目标.而这个小目标就是一个有意思的项目,通过完成这个项目,对自己的成果(也包括失败的)进行分析总结,从中提炼出对应的技术并分享出来,不断的往复,如此,为的就是让我们永远保持编写程序的兴趣和热情,完了,还提高我们的技术.而本文就是总结自己的一个小目标(基于控制台实现的贪吃蛇游戏而写的总结) 2).技术实现 大家小时候一定玩过贪吃蛇的游戏.贪吃蛇游戏的控制过程其实也不复杂.简单的可以概括为以下4个部分. 1.1  .组

java socket控制台版本聊天室程序源码下载

原文:java socket控制台版本聊天室程序源码下载 代码下载地址:http://www.zuidaima.com/share/1550463257578496.htm java socket控制台版本聊天室程序源码下载,学习的时候写的,适合学习java基础 java网络编程基础用 标签: java socket 控制台 聊天室 源码话题: 网络编程 java socket控制台版本聊天室程序源码下载,布布扣,bubuko.com

[java]基于UDP的Socket通信Demo

java课编程作业:在老师给的demo的基础上实现客户端发送数据到服务器端,服务器端接受客户端后进行数据广播. 整体功能类似于聊天室,代码部分不是太难,但是在本机测试的时候出现这样的问题: 服务端通过将每一个Socket客户端的IP存入Set集合,每次接受到数据后都向当前所有的IP转发.但是本机演示的时候所有开的ChatClient客户端都是同一IP,怎么测试呢? 解决办法就是本机测试时候服务端向多个不同的端口转发就好了,这样跑起来的客户端是在不同端口上进行监听的(只是为了实现广播,实际应用下还