结对编程——小学四则运算

一.简介

个人信息

姓名学号gitCode地址
黄翊森3121005168GitCode黄翊森
王宗奎3121005183GitCode王宗奎

作业

这个作业属于哪个课程21级软件工程
这个作业要求在哪里结对编程:小学四则运算
这个作业的目标实现一个自动生成小学四则运算题目的命令行程序
其他参考文献CSDN

二.PSP表格

PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划6060
· Estimate· 估计这个任务需要多少时间12001200
Development开发800800
· Analysis· 需求分析 (包括学习新技术)3025
· Design Spec· 生成设计文档2015
· Design Review· 设计复审1530
· Coding Standard· 代码规范 (为目前的开发制定合适的规范)2010
· Design· 具体设计240300
· Coding· 具体编码120150
· Code Review· 代码复审4020
· Test· 测试(自我测试,修改代码,提交修改)2015
Reporting报告5050
· Test Report· 测试报告2020
· Size Measurement· 计算工作量1010
· Postmortem & Process Improvement Plan· 事后总结, 并提出过程改进计划2020
· 合计960885

三.接口的设计与实现过程

3.1系统主体设计

  • 程序分为两个模块,主实现和工具包。
  • 主实现内包括出题模块和判断正确与否的模块。
  • 工具包内包括分词工具,以及文件处理工具。

3.2各个模块设计

3.2.1 操作数类
  • Operator类

  • 操作数类是该程序的主体类。

  • 有两个主要的属性,分子以及分母。

  • 操作数类中有个8个方法实现:
    1.求该操作数分子分母的最大公因数
    2.将分子除以最大公约数,得到最简真分数的分子
    3.将分母除以最大公约数,得到最简真分数的分母
    4.运算操作。包括加减乘除(共4个方法)。
    5.重写toString方法。

3.2.2 计算类
  • Calculate类
  • 计算类包括三个方法:
    1.将传入的中缀式的题目转换成后缀式。
    2.将后缀式题目进行分词,对分词后的存有操作数和操作符的栈进行出入栈处理,调用计算方法。
    3.计算的实现(返回float类型)。
3.2.3 出题类
  • 出题类在用户输入生成题目的数量后,开始生成题目,并对题目进行一些逻辑处理。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fLFPcMJL-1678879072421)(C:\Users\86173\AppData\Local\Temp\WeChat Files\c37673e81576958ce434d5af7d5e015.png)]

3.2.4 判断类
  • 判断类会根据用户输入的答案和正确答案,进行比对,将结果写入成绩文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dnSOUOPM-1678879072422)(C:\Users\86173\AppData\Local\Temp\WeChat Files\0d06add05548b6ad84ea96d91f4d3fb.png)]

3.2.5 分词类
  • HandleFractionUtils类。
  • 将题目分词,分别将操作数、操作符放入栈中。
3.2.6 文件操作类
  • FileUtils类。
  • 将之前已经生成过了的题目和答案清除掉,防止影响后续测试结果。

四.接口部分的性能改进

4.1 性能分析图

出题模块
  • 以20道题目为例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Kai0I7j-1678879072423)(C:\Users\86173\AppData\Local\Temp\WeChat Files\3eadd9fe04ec5e435266b0452e20fb0.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vtHaG4Bw-1678879072423)(C:\Users\86173\AppData\Local\Temp\WeChat Files\0797fe5f98090e5bf3aab619ce26124.png)]

判断正误模块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ek5YRGBx-1678879072424)(C:\Users\86173\AppData\Local\Temp\WeChat Files\35261211fffed4ad2ba109cfde5340f.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4TlDbHxs-1678879072424)(C:\Users\86173\AppData\Local\Temp\WeChat Files\0797fe5f98090e5bf3aab619ce26124.png)]

4.2 性能改进

  • 完成地比较仓促,没有怎么对性能进行改进。

五.代码说明

5.1 生成中缀表达式

  • 中缀表达式,即日常所见的四则运算表达式。
  • 为了测试方便,将数值输入范围限定到0~9之间,并随机输入,总题目数和分数题目的个数也随机。
Random random = new Random();
Operator operator = new Operator();
HandleFractionUtils fractionUtils = new HandleFractionUtils();
Scanner scanner = new Scanner(System.in);
OperatorUtils operatorUtils = new OperatorUtils();
int i,j;
//操作符数量。
int operationCount;
//操作符。
char operation;
int isUsedFraction;
int number1, tempNumber;
int number = 0;
FileUtils.clearFile("QuestionsAnswers.txt");
FileUtils.clearFile("Questions.txt");
System.out.println("输入生成的题目的数量:");
int questionsCount = scanner.nextInt();
outer:
for (i = 1; i <= questionsCount; i++) {
   StringBuilder questionBuilder = new StringBuilder();
   isUsedFraction = random.nextInt(2) + 1;
   operationCount = random.nextInt(3) + 1;
   if (isUsedFraction % 2 == 0) {
      number1 = random.nextInt(10);
      questionBuilder.append(number1);
      for (j = 1; j <= operationCount; j++) {
         //获得随机的运算符
         operation = operatorUtils.makeOperator();
         questionBuilder.append(operation);
         tempNumber = random.nextInt(10);
         if (operation == '÷' && tempNumber == 0) {
            tempNumber = random.nextInt(9) + 1;
         }
         if ((j == 1 && operation == '÷' && number1 % tempNumber != 0) || (operation == '÷' && number % tempNumber != 0)) {
            i--;
            continue outer;
         }
         number = tempNumber;
         questionBuilder.append(number);
         //排除负数的情况
         if (Calculate.calculateWithEnding(Calculate.moveIntOperation(questionBuilder.toString())) < 0) {
            i--;
            continue outer;
         }
      }
   }
   //若有余数,则取分数。
   else {
      for (j = 1; j <= operationCount + 1; j++) {
         //分母为4到8的随机数
         operator.setDenominator(random.nextInt(5) + 4);
         //分子为1到3的随机数
         operator.setNumerator(random.nextInt(3) + 1);
         /*operator.handleNumerator(operator);
         operator.handleDenominator(operator);*/
         int num1 = operator.getNumerator();
         int num2 = operator.getDenominator();
         if (j <= operationCount) {
            //生成运算符
            operation = operatorUtils.makeOperator();
            //字符串拼接,生产题目
            questionBuilder.append(num1).append('/').append(num2).append(" ").append(operation).append(" ");
         } else {
            questionBuilder.append(num1).append('/').append(num2);
            String tempStr = fractionUtils.toHandle(Calculate.moveFractionOperator(questionBuilder.toString()));
            if (tempStr == null) {
               i--;
               continue outer;
            } else if (tempStr.charAt(0) == '-') {
               i--;
               continue outer;
            }
         }
      }
   }

5.2计算答案

  • 计算答案的代码。
/**
	 * 用后缀式的题目进行计算。
	 *
	 * @param endingQuestion 以后缀式表达的题目
	 * @return 返回结果
	 */
	public static float calculateWithEnding(String endingQuestion) {
		Stack<Float> endingStack = new Stack<>();
		char[] endingArr = endingQuestion.toCharArray();
		//如果是操作数,则推到堆栈
		for (Character ch : endingArr) {
			if (ch >= '0' && ch <= '9') endingStack.push((float) (ch - '0'));
				// 如果是运算符,则计算结果
				// 在堆栈中有前2个操作数的情况下,将结果推送到堆栈中
			else endingStack.push(getResult(ch, endingStack.pop(), endingStack.pop()));
		}
		//返回表达式结果
		return endingStack.pop();
	}

/**
 * 获得结果
 *
 * @param operation 运算符
 * @param f1        操作数1
 * @param f2        操作数2
 * @return 返回结果
 */
public static float getResult(char operation, float f1, float f2) {
   if (operation == '+') {
      return f2 + f1;
   } else if (operation == '-') return f2 - f1;
   else if (operation == '*') return f2 * f1;
   else if (operation == '÷') return f2 / f1;
   else return (float) -0;
}

六.单元测试展示

  • 以输入20道题目为例子,生成的题目如下:
    在这里插入图片描述

  • 答案如下:
    在这里插入图片描述

  • 用户答题情况(假设用户3、8、10、12题出错)以及结果判断如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jcVSUN7O-1678879072426)(C:\Users\86173\AppData\Roaming\Typora\typora-user-images\image-20230315184415097.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-puFOOU0Z-1678879072426)(C:\Users\86173\AppData\Roaming\Typora\typora-user-images\image-20230315184434559.png)]

七.个人小结

黄翊森

这是我第一次与其他人合作完成一个项目,一定程度上提高了我的团队协作能力。本次任务相比上次任务而言,难度有所增加,在面对一些问题时,也参考了许多资料,比如使用逆波兰函数计算结果,将算术的中缀形式改成后缀形式,减少了处理运算部分逻辑实现的难度;同时,本次项目又一次运用了分词的操作,能让我更好地理解Java中的Tokenizer类,对其一些基本用法了解更为透彻,不再像第一次使用时那样茫然无措。总而言之,此次项目经历也使我的代码能力有所提高,收获颇丰。

对于结对编程,给我带来许多好处,首先,面对问题时,能有人与我一同解决,例如在计算最大公约数时,出现最大公约数为0的情况,我们两个人各自检查代码,结合互联网上的资料,一起将这个问题解决;同时,也能让我们在分配好任务的前提下,合理高效地完成各自的任务,本次我主要完成计算模块的实现以及操作数类的定义和方法实现,最后再将两个人的代码相互融合,顺利完成本次任务。

王宗奎

本次结对编程,让我体会到合作编程的优势,我们两个人在同一个宿舍,在任务分配和遇到问题时,都能方便地进行沟通解决,不需要再一个人孤军奋战,很大程度上提高了完成任务的效率。同时,本次编程任务也提高了我的编程能力,更好地掌握了Java语言,也让我养成良好的编程习惯,对方法和类的命名规范有所了解。由于时间较为紧迫,还有部分问题还尚待解决,也算是遗憾,但还是让我收获颇丰。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值