此作业要求源于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2166
一、需求分析:
1.功能需求
1)命令行程序接受一个数字输入
2)输出相应数目的四则运算题目和答案
3) 运算式子必须至少有两个运算符
4)运算数字在 100 之内的正整数
5)答案不能是负数
2.扩展要求
1) 能出和真分数相关的练习题
2) 能处理用户输入的真分数,并判断对错,打分统计
二、开发环境、软件、语言
开发环境:Windows 10
开发软件:IntelliJ IDEA 2018.2.2 x64
开发语言:Java
三、实现思路
主要功能:判断用户输入的数据是否是正整数,如果是就下一步,不是就让用户重新输入,根据用户输入的题目数生成相应道题目及答案,使用for循环语句,条件就是用户输入的题目数。随机生成一个3~5个运算数字之间的作为一道运算题的运算长度,使用switch(运算长度)语句来判断生成一道题的题目及结果。计算该题目的运算结果主要使用 if else 判断语句,如果计算得到的结果小于1,就重新生成题目,否则,就将题目与运算的结果写进文本中,并打印输出题目与结果在屏幕上。
扩展功能:实现真分数运算的的思路与主要功能的类似。生成10道真分数运算题,随机生成2~3个真分数长度的运算式,随机生成分子、分母分别存进各自的数组里,根据运算长度随机产生符号数,如果是两个运算符就判断运算符号的优先级,根据优先级来计算真分数运算的结果。实现真分数运算用到两个函数,一个是真分数运算函数,这个函数需要传进五个参数:两个运算的分数的分子与分母,以及一个运算符号,计算的结果存到结果数组中;另一个是分数约分函数,题目运算完之后就是约分,约分需要计算出分子与分母的最大公因数,这里用到一个for循环语句,将循环变量 i 初始化为1,将分子、分母分别对 i 进行取余,如果余数都为0,则将 i 旳值赋给保存最大公因数得变量,i++,然后进行下一次循环,直到 i 等于分子,得到最终的最大公因数。将分子,分母分别除以最大公因数就得到约分的最终结果。判断结果的分子是否大于0并且是否小于分母,如果是就将题目与结果写进文本,并打印输出题目让用户作答,判断用户输入结果的正确与否计算其最终得分;否则就重新生成题目。
四、个人软件过程耗时估计与统计表
Personal Software Process Stages | Time Senior Student | Time | |
Planning | 计划 | 72 | 70 |
Estimate | 估计这个任务需要多少时间 | 80 | 72 |
Development | 开发 | 53 | 56 |
Analysis | 需求分析 (包括学习新技术) | 5 | 8 |
Design Spec | 生成设计文档 | 3 | 3 |
Design Review | 设计复审 | 2 | 3 |
Coding Standard | 代码规范 | 1 | 0.5 |
Design | 具体设计 | 5 | 4 |
Coding | 具体编码 | 45 | 50 |
Code Review | 代码复审 | 3 | 2 |
Test | 测试(自我测试,修改代码,提交修改) | 5 | 3 |
Presentation | 报告 | 4 | 3 |
Test report | 测试报告 | 1 | 2 |
Computational effort | 计算工作量 | 0.5 | 1 |
Propose process improvement plan | 并提出过程改进计划 | 1 | 2 |
五、主要代码
四则混合运算部分代码如下:
1 case 3: 2 if (operators[op1] == "+") { 3 if (operators[op2] == "+") { 4 result = data1 + data2 + data3; 5 System.out.println(str1 + "=" + result); 6 printWriter.println(str1 + "=" + result); 7 } else if (operators[op2] == "-") { 8 result = data1 + data2 - data3; 9 if (result <= 0) { 10 i--; 11 } else { 12 System.out.println(str1 + "=" + result); 13 printWriter.println(str1 + "=" + result); 14 } 15 } else if (operators[op2] == "*") { 16 result = data1 + data2 * data3; 17 System.out.println(str1 + "=" + result); 18 printWriter.println(str1 + "=" + result); 19 } else if (operators[op2] == "/") { 20 result = data1 + data2 / data3; 21 if (result <= 0 || data2 % data3 != 0) { 22 i--; 23 } else { 24 System.out.println(str1 + "=" + result); 25 printWriter.println(str1 + "=" + result); 26 } 27 } 28 } else if (operators[op1] == "-") { 29 if (operators[op2] == "+") { 30 result = data1 - data2 + data3; 31 if (result < 0) { 32 i--; 33 } else { 34 System.out.println(str1 + "=" + result); 35 printWriter.println(str1 + "=" + result); 36 } 37 } else if (operators[op2] == "-") { 38 result = data1 - data2 - data3; 39 if (result < 0) { 40 i--; 41 } else { 42 System.out.println(str1 + "=" + result); 43 printWriter.println(str1 + "=" + result); 44 } 45 } else if (operators[op2] == "*") { 46 result = data1 - data2 * data3; 47 if (result <= 0) { 48 i--; 49 } else { 50 System.out.println(str1 + "=" + result); 51 printWriter.println(str1 + "=" + result); 52 } 53 } else if (operators[op2] == "/") { 54 result = data1 - data2 / data3; 55 if (result <= 0 || data2 % data3 != 0) { 56 i--; 57 } else { 58 System.out.println(str1 + "=" + result); 59 printWriter.println(str1 + "=" + result); 60 } 61 } 62 } else if (operators[op1] == "*") { 63 if (operators[op2] == "+") { 64 result = data1 * data2 + data3; 65 System.out.println(str1 + "=" + result); 66 printWriter.println(str1 + "=" + result); 67 } else if (operators[op2] == "-") { 68 result = data1 * data2 - data3; 69 if (result <= 0) { 70 i--; 71 } else { 72 System.out.println(str1 + "=" + result); 73 printWriter.println(str1 + "=" + result); 74 } 75 } else if (operators[op2] == "*") { 76 result = data1 * data2 * data3; 77 System.out.println(str1 + "=" + result); 78 printWriter.println(str1 + "=" + result); 79 } else if (operators[op2] == "/") { 80 result = data1 * data2 / data3; 81 if (result <= 0 || data2 % data3 != 0) { 82 i--; 83 } else { 84 System.out.println(str1 + "=" + result); 85 printWriter.println(str1 + "=" + result); 86 } 87 } 88 } else if (operators[op1] == "/") { 89 if (operators[op2] == "+") { 90 result = data1 / data2 + data3; 91 if (result <= 0 || data1 % data2 != 0) { 92 i--; 93 } else { 94 System.out.println(str1 + "=" + result); 95 printWriter.println(str1 + "=" + result); 96 } 97 } else if (operators[op2] == "-") { 98 result = data1 / data2 - data3; 99 if (result <= 0 || data1 % data2 != 0) { 100 i--; 101 } else { 102 System.out.println(str1 + "=" + result); 103 printWriter.println(str1 + "=" + result); 104 } 105 } else if (operators[op2] == "*") { 106 result = data1 / data2 * data3; 107 if (result <= 0 || data1 % data2 != 0) { 108 i--; 109 } else { 110 System.out.println(str1 + "=" + result); 111 printWriter.println(str1 + "=" + result); 112 } 113 } else if (operators[op2] == "/") { 114 result = data1 / data2 / data3; 115 if (result <= 0 || data1 % data2 != 0 || data1 / data2 % data3 != 0) { 116 i--; 117 } else { 118 System.out.println(str1 + "=" + result); 119 printWriter.println(str1 + "=" + result); 120 } 121 } 122 } 123 break;
真分数运算部分代码如下:
1 case 3: 2 for (k = 0; k < 3; k++) { 3 denominator[k] = (int) (Math.random() * 100 + 1); 4 numerator[k] = (int) (Math.random() * denominator[k] + 1); 5 } 6 rand1 = (int) (Math.random() * 4); 7 rand2 = (int) (Math.random() * 4); 8 if (rand1 == 2 || rand1 == 3) { //如果第一个运算符是乘或者除就先算 9 calculateProperFraction(numerator[0], denominator[0], rand1, numerator[1], denominator[1]); 10 calculateProperFraction(properFractionResult[0], properFractionResult[1], rand2, numerator[2], denominator[2]); 11 } else { 12 calculateProperFraction(numerator[1], denominator[1], rand2, numerator[2], denominator[2]); 13 calculateProperFraction(numerator[0], denominator[0], rand1, properFractionResult[0], properFractionResult[1]); 14 } 15 reductionFraction(properFractionResult[0], properFractionResult[1]); 16 properFractionTitle[i] = numerator[0] + "/" + denominator[0] + " " + operators[rand1] + " " + numerator[1] + "/" + denominator[1] + " " + operators[rand2] + " " + numerator[2] + "/" + denominator[2] + " = "; 17 break;
分数运算:
1 //计算两个分数的运算结果 2 private static void calculateProperFraction(int numerator1,int denominator1,int rand,int numerator2,int denominator2){ 3 switch (rand){ 4 case 0://如果是加号 5 properFractionResult[1]=denominator1*denominator2; 6 properFractionResult[0]=numerator1*denominator2+numerator2*denominator1; 7 break; 8 case 1://如果是减号 9 properFractionResult[1]=denominator1*denominator2; 10 properFractionResult[0]=numerator1*denominator2 - numerator2*denominator1; 11 break; 12 case 2://如果是乘号 13 properFractionResult[1]=denominator1*denominator2; 14 properFractionResult[0]=numerator1*numerator2; 15 break; 16 case 3://如果是除号 17 properFractionResult[1]=denominator1*numerator2; 18 properFractionResult[0]=numerator1*denominator2; 19 break; 20 } 21 }
分数约分:
1 //将分数约分约到最简 2 private static void reductionFraction(int numerator,int denominator){ 3 int i=0; 4 int reductionFractionNumerator=0,reductionFractionDenominator=0; //约分后的的分子、分母 5 int commonDivisor=1; 6 for (i=numerator;i>=1;i--){ 7 if (numerator%i==0 && denominator%i==0){ 8 commonDivisor=i; 9 break; 10 } 11 } 12 reductionFractionNumerator=numerator/commonDivisor; 13 reductionFractionDenominator=denominator/commonDivisor; 14 properFractionResult[0]=reductionFractionNumerator; //约分后的的分子赋给properFractionResult[0] 15 properFractionResult[1]=reductionFractionDenominator; //约分后的的分母赋给properFractionResult[1] 16 }
六、运行效果截图
四则运算功能实现效果截图:
扩展功能实现效果图:
七、遇到的问题与解决方法
一开始想把这个程序写成一个函数只做一件事情的,但最终并没有实现,暂时又没有很好的想法,于是这代码就弃置一边了。我重新写了程序,我的四则混合运算还是那种一个函数实现全部功能的老路。我发现在实现四则运算式运算的时候,重复的代码实在是太多了,如果是计算有四个运算符的算术式的结果就要两千多行代码(亲自写完,然后删了。对于写这么多的重复代码,感觉非常不好,就换成了2~3个运算符长度的算术式)。后来,我做到扩展功能的时候,发现这也是要遇到那个计算的问题,我又不想写那么多的重复代码,于是我又想到那个一个函数只做一件事情的方法,我不死心又做了一次,这次却实现了,计算的那个函数只做计算这一件事,也只有这个函数做计算。我想到是算术式长度较短让我实现了这功能,如果算术式较长的话就会出现另一个的问题——在判断运算符的计算顺序的问题,en,这个问题暂时还没有想到解决的方法。
八、代码提交
代码只有一个 Arithmetic.java 文件, Arithmetic.java 源代码文件以及Arithmetic.exe可运行程序都已提交到了我的远程仓库GitHub上。
这是我的GitHub远程仓库地址:https://github.com/Trojanpa/test