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

    1.仓库地址:https://git.coding.net/FrrLolix/Calculate.git

    2.需求分析:

      ①程序接受一个输入的参数n后,随机生成n道四则运算式,其中要保证生成的运算式的运算符在3-5个之间,同时程序对生成的运算式自动求解,结果和运算式一同输出到result.txt文件中。

      ②因为面向对象是小学生,所以要保证生成的运算式中不出现负数和小数,运算的结果也不能出现负数和小数。

      ③程序需要判断输入的参数n是否合法,在不合法时要进行一定的处理。

      ④在原有的基础上,生成的运算式随机性的带有括号和真分数。

    3.功能设计:

      ①基本功能:

        Ⅰ程序接收参数n,并对n的合法性作出判断,若出现错误则提示。

        Ⅱ自动生成n个运算式,并计算得出结果。

        Ⅲ将计算后的结果与运算式一同存入txt文件中,保存在指定目录下。

      ②扩展功能:

        Ⅰ由于面向对象是小学生,因此数字在0-100之间。

        Ⅱ随机产生括号并保证括号的合法有效性。

        Ⅲ加入分数运算式,并且保证计算前后都是真分数,且不可化简。

    4.设计实现:

      ①整体思路:

        Ⅰ四则运算:首先产生5个随机数和一个flag作为标志,flag的值为随机0-3,分别代表了不同数量的运算符和分数运算,确定了flag的值后,产生随机的运算符将数字连接,构成运算式,再将运算符和数字拆分,利用两个栈分别放置,将原本的运算式转化成后缀表达式,从而进行计算,这也是逆波兰表达式的计算方法。

        Ⅱ带括号计算:以3个运算符的计算为例,括号只能存在于前两个数字和后两个数字中,因此设置location这一参数,location为0时,括号在前,location为1时括号在后,分别进行讨论,确定括号的位置,生成带括号的运算式,在后续计算过程中,注意要增加括号的入栈和出栈操作。

        Ⅲ真分数的计算:对于真分数,首先随机产生0-100的某个数,然后随机产生一个比刚刚生成的数小的数,通过辗转相除法,生成真分数并输出。

      对于整体而言,我只使用了一个类,通过这个类来调用不同的方法解决问题。

      ②设计的函数:

        Ⅰ构成3个运算数的运算式的方法: three(int n1,int n2,int n3)

        Ⅱ构成4个运算数的运算式的方法:four(int n1,int n2,int n3,int n4)

        Ⅲ构成5个运算数的运算式的方法:five(int n1,int n2,int n3,int n4,int n5)

        Ⅳ实现计算的方法:Calculate(String s)

        Ⅴ分式化简的方法:gcd(int a,int b)

    5.代码详情:

      ①生成表达式的算法:

        Ⅰ这里使用一个循环,flag用于判断每次循环产生的结果,根据flag的不同调用不同的方法

    for(i=0;i<n;i++){
        int n1=ran.nextInt(100);//生成一个0-100的整数
        int n2=ran.nextInt(100);
        int n3=ran.nextInt(100);
        int n4=ran.nextInt(100);
        int n5=ran.nextInt(100);
        int flag=ran.nextInt(4);//随机生成一个0-3的整数,0表示3个运算数,1表示4个运算数,2表示5个运算数,3表示分数计算

        Ⅱ此处是flag=3时,分数的生成方法

    n1=1+ran.nextInt(101);
    n2=1+ran.nextInt(101);
    n3=1+ran.nextInt(101);
    int M,Z;
    int x1,x2,x3;
    x1=1+ran.nextInt(n1);//生成一个比分母n1小的分子,实现真分数
    x2=1+ran.nextInt(n2);//生成一个比分母n2小的分子,实现真分数
    x3=1+ran.nextInt(n3);//生成一个比分母n3小的分子,实现真分数
    Z=x1*n2*n3+x2*n1*n3+x3*n1*n2;
    M=n1*n2*n3;
    String d=gcd(Z,M);
    s=x1+"/"+n1+"+"+x2+"/"+n2+"+"+x3+"/"+n3+"="+d;
    pw.write(s+"
    "); // 
    即为换行
        Ⅲ此处是3个运算符是运算式的生成方法,我在这里进行了讨论,加入了是否有括号的两种情况,对于括号的位置进行设定,随后输出不同的结果,此处代码较长,只展示一部分,详细的可以在Coding.net上查询
    String s1= new String();
    Random ran = new Random();
    int sign1=ran.nextInt(4);//随机生成一个0-3的整数,0表示加法,1表示减法,2表示乘法,3表示除法
    int sign2=ran.nextInt(4);
    int sign3=ran.nextInt(2);//如果是1表示有括号,如果是0 表示无括号
    int sign4=ran.nextInt(2);//如果是1表示产生分式,如果是0 表示整式。
    
    if(sign1==sign2)
    {
        sign2=(sign1+1)%3;//保证两个运算符不相同。
    }
    
    if(sign3==0)//表示无括号
    {
        //下面的过程为排除,除不整的,还有分母为0,
    
        if(sign2==3)
        {
            if(n3==0)//如果分母为0
                n3=1+ran.nextInt(100);//随机生成一个1-100的整数
            while(n2%n3!=0)
            {
                n2=ran.nextInt(100);
            }
        }

      ②计算方法

        Ⅰ计算方法我采用了逆波兰表达式的算法,这一部分是之前困扰我最久的地方,起初想了许多方法来尝试,但都有些繁琐,实施起来并不是很容易,因此我也在其他博客上参考学习了许多,最终选定了逆波兰表达式,逆波兰表达式的思路为
      1.遇到操作数:直接输出(添加到后缀表达式中)
      2.栈为空时,遇到运算符,直接入栈
      3.遇到左括号:将其入栈
      4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
      5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
      6.最终将栈中的元素依次出栈,输出。
      下面截取了遇到等号时的代码处理。
    case '(': {
                            stack2.push(String.valueOf(c));//如果是(   转化为字符串压入字符栈
                            break;
                        }
                        case ')': {//遇到右括号了计算,因为(的优先级最高
                            String stmp = stack2.pop();//如果是),将符号栈栈顶元素取到
                            while (!stack2.isEmpty() && !stmp.equals("(")) { //当前符号栈里面还有+ - * /
                                int a = stack1.pop();  //取操做数a,b
                                int b = stack1.pop();
                                int sresulat = calculate(b, a, stmp);
                                if(sresulat<0)
                                    return  -1;
                                stack1.push(sresulat);//将结果压入栈
                                stmp = stack2.pop();//符号指向下一个计算符号
                            }
                            break;
                        }
    6.测试运行:
      进入src文件下,输入javac -encoding utf-8 Main.java 编译出相应的class文件,再输入java Main 进行测试:




    7.不足与改进:
      在算法的实现过程中,虽然经过了不断的修改和调整,但目前仍然存在着许多不足:

      1.括号的处理,只是处理了几种特殊情况,并没有做到括号的随机并合理,没有涉及到多重括号的生成和处理,这也是以后改进的一个方向。

      2.在出题的过程中,我的方法是将不同数量的运算符的算法之间分离开,造成算法的延展性较差,目前也参考了同学们的代码,发现自己的代码如果扩展到10个运算符的情况,会很麻烦,这是接下来需要改进的一点。

      3.在最开始进行算法的分析的时候,没有注意题目的要求,也没有看到老师推荐的调度场算法,因此,在计算上大费周章,这是今后要避免的一个问题,对于项目要求一定要认真理解。

    8.项目总结:

      1.在算法的编写过程中,采用了书中和老师所推荐的“逐步求精”的设法方法,将一个项目分解成几个不同的小问题,通过编写不同的方法来逐步解决每个问题,各个方法相互配合,循序渐进,最终达成自己想要的结果。

      2.对于算法编写中出现的许多问题,进行了思考和改进,并且对于项目的延展性有了更深的理解,我的算法延展性不强,这是以后和强化的一点。

    9.PSP展示
      

    PSP2.1

    任务内容

    计划共完成需要的时间(min)

    实际完成需要的时间(min)

    Planning

    计划

    8

    10

    ·        Estimate

    ·   估计这个任务需要多少时间,并规划大致工作步骤

    8

    6

    Development

    开发

    600

    1200

    ·        Analysis

    ·         需求分析 (包括学习新技术)

    20

    30

    ·        Design Spec

    ·         生成设计文档

    10

    10

    ·        Design Review

    ·         设计复审 (和同事审核设计文档)

    5

    5

    ·        Coding Standard

    ·         代码规范 (为目前的开发制定合适的规范)

    3

    5

    ·        Design

    ·         具体设计

    10

    20

    ·        Coding

    ·         具体编码

    500

    950

    ·        Code Review

    ·         代码复审

    10

    20

    ·        Test

    ·         测试(自我测试,修改代码,提交修改)

    15

    30

    Reporting

    报告

    10

    30

    ·         Test Report

    ·         测试报告

    5

    10

    ·         Size Measurement

    ·         计算工作量

    1

    1

    ·         Postmortem & Process Improvement Plan

    ·         事后总结, 并提出过程改进计划

    5

    15


        
      
  • 相关阅读:
    相交链表 3种方法
    旋转数组 空间复杂度为O(1) 的2 种方法 + 1种空间复杂度O(n)
    各种sort排序总结
    我写过的bug...
    裸BFS题若干
    luence
    mysql 找出外键等约束
    mysql (8.0 或以下)数据 卸载, 安装, 创建用户, 赋权
    navicat 导入sql文件 的正确方法
    [转] git clone 远程分支
  • 原文地址:https://www.cnblogs.com/FrrLolix/p/8638657.html
Copyright © 2011-2022 走看看