《JAVA程序设计》结对编程联系_四则运算(第二周:整体性总结)
结对对象与其博客链接
20175312陶光远:https://www.cnblogs.com/20175312-tgy/p/10697238.html
需求分析
(一)功能需求
1.自动生成题目(上周已完成)
可生成包含不同运算符个数的题目
2.题目运算(判题)(真分数上周已经完成,运算和后缀计算这周已完成)
实现中缀表达式转为后缀表达式并计算
判断用户答题正误,并输出正确结果
3.支持真分数(上周已完成)
实现分数算式的计算
3.题目去重(扩展需求)
实现对自动生成表达式中相同题目的去重
(二)对需求的理解:
1.能随机生成多道四则运算题目,可由用户输入控制
2.支持整数和真分数
3.支持多运算符,运算符个数可由用户输入控制
4.能够判断正误,错误时能提醒并输出正确答案
5.可以计算正确率
设计思路
1.我对支持多运算符的理解就是为:在输出前,由用户输入所要求的运算符个数,然后程序运行自动给出相应算式。
2.上周基本就构思完成了,这周是集中实现,中缀转后缀然后计算也做出来了。
3.由于学习c语言的时候曾设计过类似于这样的四则运算的程序,可以说思路上并没有问题。
4.总体思路就是这样了,具体思路见下面的UML类图。
UML图

实现过程中的关键代码解释(本周完成的部分)
1.计算一个后缀表达式的函数(Jisuan.java)
package size;
import java.util.Stack;
public class Jisuan {
    String [] str1;
    String result;//结果储存
    public Jisuan (String jisuan)//构造用于计算一个后缀表达式的函数
    {
        str1=jisuan.split("\\s");
    }
    public RationalNumber toRationalNumber(String num) //转换为RationalNumber类的对象的方法
    {
        if (num.contains("/")==false){
            int a =Integer.parseInt(num);
            RationalNumber rationalNumber1 =new RationalNumber(a,1);
            return rationalNumber1;
        }
        else {
            String[] Array =num.split("/");
            int numerator = Integer.parseInt(Array[0]);
            int denominator=Integer.parseInt(Array[1]);
            RationalNumber rationalNumber2 =new RationalNumber(numerator,denominator);
            return rationalNumber2;
        }
    }
    public void ToResult()//计算中缀表达式,转移结果到先前声明的result
    {
        Stack stack1=new Stack();
        int start =0;
        while (start<str1.length){
            if (str1[start].equalsIgnoreCase("+")==false&&str1[start].equalsIgnoreCase("-")==false&&str1[start].equalsIgnoreCase("×")==false&&str1[start].equalsIgnoreCase("÷")==false){
                stack1.push(str1[start]);
            }
            else
            if (str1[start].equalsIgnoreCase("+")==true){
                RationalNumber num1=this.toRationalNumber(String.valueOf(stack1.peek()));
                stack1.pop();
                RationalNumber num2=this.toRationalNumber(String.valueOf(stack1.peek()));
                stack1.pop();
                RationalNumber finish =num2.add(num1);
                String str3=finish.toString();
                stack1.push(str3);
            }
            else
            if (str1[start].equalsIgnoreCase("-")==true){
                RationalNumber num1=this.toRationalNumber(stack1.peek().toString());
                stack1.pop();
                RationalNumber num2=this.toRationalNumber(stack1.peek().toString());
                stack1.pop();
                RationalNumber finish =num2.subtract(num1);
                String str3=finish.toString();
                stack1.push(str3);
            }
            else
            if (str1[start].equalsIgnoreCase("×")==true){
                RationalNumber num1=this.toRationalNumber(stack1.peek().toString());
                stack1.pop();
                RationalNumber num2=this.toRationalNumber(stack1.peek().toString());
                stack1.pop();
                RationalNumber finish =num2.multiply(num1);
                String str3=finish.toString();
                stack1.push(str3);
            }
            else
            {
                RationalNumber num1=this.toRationalNumber(String.valueOf(stack1.peek()));
                stack1.pop();
                RationalNumber num2=this.toRationalNumber(String.valueOf(stack1.peek()));
                stack1.pop();
                RationalNumber finish =num2.divide(num1);
                String str3=finish.toString();
                stack1.push(str3);
            }
            start++;
        }
        String str4=stack1.peek().toString();
        result=str4;
    }
    public String getResult()//计算结果
    {
        return result;
    }
}
2.将一个中缀表达式转换为对应的后缀表达式的函数(Qzh.java)
package size;
import java.util.Stack;
public class Qzh {
    String former;//中缀表达式
    String last;//后缀表达式
    public Qzh(String former)//构造将一个中缀表达式转换为对应的后缀表达式的函数
    {
        this.former=former;
        last="";
    }
    public String getLast() //得到后缀表达式
    {
        return last;
    }
    public void qzh() //将中缀表达式转为后缀表达式
    {
        String []str1=former.split("\\s");
        String [] str2=new String[str1.length-1];
        for (int a=0;a<str1.length-1;a++)
            str2[a]=str1[a];
        Stack stack=new Stack();
        int num2=0;
        while (num2<str2.length){
            if(str2[num2].equalsIgnoreCase("+")==false&&str2[num2].equalsIgnoreCase("-")==false&&str2[num2].equalsIgnoreCase("×")==false&&str2[num2].equalsIgnoreCase("÷")==false)
                last+=str2[num2]+" ";
            else
            if (stack.empty()==true)
                stack.push(str2[num2]);
            else
            if ((stack.peek().equals("+")==true||stack.peek().equals("-")==true)&&(str2[num2].equalsIgnoreCase("×")||str2[num2].equalsIgnoreCase("÷")))
                stack.push(str2[num2]);
            else {
                last+=stack.peek()+" ";
                stack.pop();
                stack.push(str2[num2]);
            }
            num2++;
        }
        while (stack.empty()==false){
            last+= stack.peek()+" ";
            stack.pop();
        }
    }
}
测试方法
总测试以及回馈代码(ZTest.java)
package size;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Scanner;
public class ZTest {
    public static void main(String[] args) {
        int ysf; //运算符个数
        int num;  //题目个数
        
        int zhengque=0;  //正确数
        double zhengquelv;  //正确率
        String []Question;  //存放题目的数组
        Scanner scanner=new Scanner(System.in);
        System.out.print("题目个数: ");
        num=scanner.nextInt();
        Question=new String[num];//保存题目至特定数组
        System.out.print("每个题目的运算符个数: ");
        ysf=scanner.nextInt();
        Timushengcheng timushengcheng=new Timushengcheng(num,ysf);
        timushengcheng.QuestionNum();
        Question=timushengcheng.getArraylist();
        int start=0;
        while (start<num)
        {
            System.out.println("第"+(start+1)+"题: "+Question[start]+"\n"+"你的计算结果: ");
            String answer=scanner.next();
            Qzh trans=new Qzh(Question[start]);
            trans.qzh();
            String qzhed =trans.getLast();
            Jisuan  calcu=new Jisuan(qzhed);
            calcu.ToResult();
            String result=calcu.getResult();
            if (answer.equals(result)==true)
            {
                zhengque++;
                System.out.println("正确答案: "+result+" ,正确,继续作答");
                System.out.println();
            }
            else
            {
                System.out.println("正确答案: "+result+" ,错误,请继续作答");
                System.out.println();
            }
            start++;
        }
        System.out.println();
        zhengquelv=(double)zhengque/num;
        DecimalFormat fmt=new DecimalFormat("0.####");
        String accurancy2=fmt.format(zhengquelv);
        Double accurancy3=Double.valueOf(accurancy2);
        NumberFormat format = NumberFormat.getPercentInstance();
        System.out.println("共"+num+"道题目,答对"+zhengque+"道题目"+"\n正确率为: "+format.format(accurancy3));
        System.out.println();
        if (accurancy3<0.6)
        {
            System.out.println("不及格!");
        }
        else{
            if (accurancy3<0.9)
                System.out.println("良好!");
            else
                System.out.println("优秀");
        }
    }
}
运行过程截图
成功运行的截图如下(总测试):

代码托管地址和码云链接
1.码云链接如下:
https://gitee.com/Lyh20175309/java-besti-is-lyh/tree/master/jiedui/src/size
2.代码托管截图:

遇到的困难:
第二周的任务并没有遇到太大的困难,
这个任务的完成,大致经历了两个阶段:
1.整理上周的思路,开始处理计算部分
2.完成计算部分,构建测试文件,也就是最终汇总计算正确率回馈的部分
主要有两个问题:
(一)在编译的过程中提示“某些输入文件使用了未经检查或不安全的操作,请使用 -Xlint:unchecked 重新编译。”,导致编译失败。
解决办法:
1.首先按照提示所说使用-Xlint:unchecked重新编译,发现失败
2.后来在网上查询,在类的前面加上@SuppressWarnings("unchecked")
即
@SuppressWarnings("unchecked")
public class Jisuan{
                    
}
3.原因:JAVA是一门安全性比较高的语言,它在编译之类要进行类型等一系列的检查。如果你使用了注解就可以告诉编译器不用检查,这样子就可以避过编译时期间的安全检查,这样子的效率会提高 。但同时安全性就大打折扣了。
参考博客链接:https://blog.csdn.net/abysstoabyss/article/details/16986731
(二)自己检测时发现了bug:除数为0的时候仍能输出答案

解决方案:结对的伙伴暂时还没有发现这个问题,我决定先写完博客再与他进行交流改进(因为时间快到了)。我发现我们的问题在与除数为0的时候默认了答案永远为0,而正确的应该是“不存在”或“此题有误”。
对结对的小伙伴做出评价(重点指出需要改进的地方)
陶光远同学依旧承担了大多数的任务,并且细心的为我查缺补漏,讲解他的编程思路与“写作手法”,是我学习路上的良师益友。
唯一的问题的话可能就是没有发现除数为0的时候依然能输出答案这个bug了。
PSP
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) | 
|---|---|---|---|
| Planning | 计划 | ||
| Estimate | 估计这个任务需要多少时间 | 1100 | 1600 | 
| Development | 开发 | ||
| Analysis | 需求分析 (包括学习新技术) | 30 | 90 | 
| Design Spec | 生成设计文档 | 30 | 40 | 
| Design Review | 设计复审 (和同事审核设计文档) | 60 | 60 | 
| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 60 | 60 | 
| Design | 具体设计 | 60 | 60 | 
| Coding | 具体编码 | 700 | 1100 | 
| Code Review | 代码复审 | 60 | 60 | 
| Test | 测试(自我测试,修改代码,提交修改) | 30 | 60 | 
| Reporting | 报告 | ||
| Test Report | 测试报告 | 20 | 20 | 
| Size Measurement | 计算工作量 | 10 | 10 | 
| Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 40 | 40 | 
     |    |合计|1100|1600
 
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号