zoukankan      html  css  js  c++  java
  • 2016012063 小学四则运算练习软件项目报告

    源码仓库地址:https://git.coding.net/deervw/four-operations.git

    一、需求分析

        1.程序可从命令行接收一个输入参数n,然后随机产生n道加减乘除习题。

        2.每个数字在 0 和 100 之间,运算符3到5个。

        3.每道习题要包含3-5种运算符。

        4.所出的练习题在运算过程中不得出现负数与非整数。

        5.将学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中。

        6.支持有括号的运算式,包括出题与求解正确答案;算式中存在的括号必须大于2个,且不得超过运算符的个数。

    二、功能设计

        1.基本功能:能够根据用户输入的参数n随机产生n道符合要求的练习题,自动算出答案,并将式子与答案以文档的形式呈现。

        2.扩展功能:支持有括号的运算式,包括出题与求解正确答案。(注意,算式中存在的括号必须大于2个,且不得超过运算符的个数。)

    三、设计实现

        我设计了一个主函数和两个自定义函数,都在Main.java

        1.判断类

        功能:带参的有返回值的类,返回的是一个整数。通过返回的参数大小,从而来判断符号的优先级。

        关系:可以直接调用。

        2.共因数divisor类

        功能:带参的有返回值的类,返回的是一个整数,该整数是两个数的最大公因数。此类通过计算两个数的最大公因数,生成化简的最终结果。

        关系:可以直接调用。

    四、算法详解

        1.输入产生的题目数n:判断输入的数是否为整数,若不是则抛出异常。

    try {
        n=Integer.parseInt(args[0]);
        if(n<=0)System.out.println("请重新输入整数!");
    }
    catch (Exception e){
        System.out.println("请重新输入整数!");
    }

        2.生成随机数和运算符:将运算符存在一个数组arr里,以便可以随机生成;用rand()方法可以随机生成0-1之间的数;若不能整除或出现负数可以使用循环重新生成a和b,直到满足要求为止。

    char[] arr= {'+','-','*','÷'};
    int temp=rand.nextInt(4);
    charArr=arr[temp];
    int a=rand.nextInt(100);//数字范围 
    int b=rand.nextInt(100);
    while(a%b!=0)//判断整除
    {
      a=rand.nextInt(100);
      b=rand.nextInt(99)+1;//不能出现0
    }
    while(a<b)//判断是否出现负数
    {
      a=rand.nextInt(100);
      b=rand.nextInt(100);
    }

           3.最大公因数:保证生成的为真分数,用辗转相除法

    public static int divisor(int x,int y){
        while(1){
            if(x%y==0)return y;
            int temp=y;
            y=x%y;
            x=temp;
        }
    }

          4.计算后缀表达式:我创建了一个栈st,保存的是char类型的字符,然后我int了一个op1来分别保存两个栈顶的操作数,所以这里先用到了String.valueOf方法先将char转换成String,然后使用Integer.parseInt方法。

     int op1 = Integer.parseInt(String.valueOf(st.pop()));
     int op2 = Integer.parseInt(String.valueOf(st.pop()));
     int op = op1 - op2;
     lkj.push(op);

    五、测试运行 

    六、代码展示

        将中序表达式转化为后序表达式:

    static bool isNumber(string message)
            {
                //判断是否为整数字符串    
                int result = -1;   
                try
                {
                    result = Convert.ToInt32(message);
                    return true;
                }
                catch
                {
                    return false;
                }
            }
            //判断操作符优先级大小  
            static bool comparePriority(string op1, string op2)
            {
                return getPriorityValue(op1) > getPriorityValue(op2);
            }
    
            private static int getPriorityValue(string op1)
            {
                throw new NotImplementedException();
            }
    
            static Stack<string> changeExpression(List<string> beforeExps)
            {
                Stack<string> operand = new Stack<string>();//操作数  
                Stack<string> opertor = new Stack<string>();//操作符  
                //遍历中序表示  
                int length = beforeExps.Count;
                int len = opertor.Count;
                //判断是否为操作数    
                for (int i = 0; i < length; i++)
                {
                    string c = beforeExps[i];
                    if (isNumber(c))
                    {
                        //操作数 存在操作数栈  
                        operand.Push(c);
                    }
                    else
                    {
                        if (c == "(")
                        {
                            opertor.Push(c);
                        }
                        else if (c == ")")
                        {
                            //该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,将"("出栈    
                            while (opertor.Peek() != "(")
                            {
                                string stringvalue = opertor.Pop();
                                operand.Push(stringvalue);
                            }
                            opertor.Pop();
                        }
                        else
                        { 
                            if (len <=  0)
                            {
                                opertor.Push(c);
                                continue;
                            }//符合为左括号 直接存入运算符  
                            if (opertor.Peek() == "(")
                            {
                                opertor.Push(c);
                            }
                            else
                            {
                                //若比运算符堆栈栈顶的运算符优先级高或相等,则直接存入运算符堆栈。    
                                if (comparePriority(c, opertor.Peek()))
                                {
                                    opertor.Push(c);
                                }
                                else
                                {
                                    // 若比运算符堆栈栈顶的运算符优先级低,则输出栈顶运算符到操作数堆栈,并将当前运算符压入运算符堆栈。  
                                    string stringvalue = opertor.Pop();
                                    operand.Push(stringvalue);
                                    opertor.Push(c);
                                }
                            }
                        }
                    }
                }
                //依序取出运算符到操作数堆栈 
                while (len > 0)
                {
                    string stringvalue = opertor.Pop();
                    operand.Push(stringvalue);
                }
                //获取正常的后缀表达式  
                Stack<string> resultSt = new Stack<string>();
                while (len > 0)
                {
                    string stringvalue = operand.Pop();
                    resultSt.Push(stringvalue);
                }
                return resultSt;
            }

    七、总结:

          所谓“模块化”就是要功能独立,功能块里要明确和调试好函数之间的调用关系,以便降低程序的复杂度和更进一步的维护。比如,在我的程序中,产生随机数和计算题目这两个功能是分开的,只要在产生随机数的程序里确定好操作数是合法的,那么计算部分可以和操作数之间做到完全独立。

    八、展示PSP

    PSP2.1Personal Software Process Stages预估耗时(小时)实际耗时(小时)
    Planning 计划 1 1
    · Estimate · 估计这个任务需要多少时间 20 24
    · Analysis · 需求分析 (包括学习新技术) 1 4
    · Design Spec · 生成设计文档 0.5 0.5
    · Design Review · 设计复审 (和同事审核设计文档) 0.5 0.5
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范) 1.5 1
    · Design · 具体设计 2 2.5
    · Coding · 具体编码 2 3
    · Code Review · 代码复审 2 2
    · Test · 测试(自我测试,修改代码,提交修改) 2 1
    Reporting 报告 1 1.5
    · Test Report · 测试报告 1.5 2
    · Size Measurement · 计算工作量 1.5 1
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 1 1
     

         

      一开始我认为该程序的难点在于代码仓库的使用,这一部分没有学过,所以我以为在这上面会花掉很长的时间。但是后来学习了一段时间才发现这其实并不是难点,更难的在于代码部分,我平时没有在做代码练习,所以我的代码能力非常薄弱,感觉什么都不会,一切都得从头开始。我投入了大量的时间和精力,才勉强完成了任务,可是我还是有很多不满意的地方,但只能以后慢慢学习了。

     
  • 相关阅读:
    浅谈.NET下的多线程和并行计算系列文章索引
    浅谈.NET下的多线程和并行计算(六)线程池基础下
    浅谈.NET下的多线程和并行计算(八)Winform中多线程编程基础上
    项目优化经验——垃圾回收导致的性能问题
    浅谈.NET下的多线程和并行计算(五)线程池基础上
    站点静态资源优化合并解决方案
    浅谈.NET下的多线程和并行计算(二)线程基本知识
    浅谈.NET下的多线程和并行计算(十二)CLR via C#第三版阅读笔记(1)
    原谅我的说谎
    索爱手机GPRS的OTA设置[转]
  • 原文地址:https://www.cnblogs.com/fux137/p/8642092.html
Copyright © 2011-2022 走看看