这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/CSGrade22-34 |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230 |
这个作业的目标 | 实现一个自动生成小学四则运算题目的命令行程序 |
github地址:https://github.com/zjm726/zjm726/tree/main/3222004893/四则运算/ExerciseProduce
一、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 15 |
· Estimate | · 估计这个任务需要多少时间 | 15 | 15 |
Development | 开发 | 280 | 320 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 55 |
· Design Spec | · 生成设计文档 | 20 | 15 |
· Design Review | · 设计复审 (和同事审核设计文档) | 10 | 10 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
· Design | · 具体设计 | 40 | 50 |
· Coding | · 具体编码 | 80 | 120 |
· Code Review | · 代码复审 | 20 | 15 |
· Test | · 测试(自我测试,修改代码,提交修改) | 35 | 45 |
Reporting | 报告 | 30 | 25 |
· Test Repor | · 测试报告 | 25 | 20 |
· Size Measurement | · 计算工作量 | 5 | 5 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 5 | 5 |
· 合计 | 330 | 360 |
二、设计实现
- exercisepro负责生成题目并计算出答案
- add、sub、mul、div分别实现加减乘除
- produceop根据随机生成的参数返回符号
- getexer、getansw分别返回题目和答案
- disposeFS对分数进行约分
- judgeM对表达式e1-e2判断e1与e2的大小
- judge判断生成的题目计算过程中是否会出现负数出现则重新生成题目
- ep生成题目和答案并写入字符串
- File_IO实现文件的写入
- Myapp将两者整合实现功能
三、性能分析
四、代码说明
点击查看代码
//生成题目和答案
public static exercisepro ep(int range) {
boolean ifne=true;//判断计算工程中是否出现负数
String exer=new String();
String answ=new String();
Random random=new Random();
int operatornum=random.nextInt(3);//生成符号的数量
int fz[]=new int[operatornum+2];//生成的分子
int fm[]=new int[operatornum+2];//生成的分母
String[] operator=new String[operatornum+1];//生成的符号
int ifbra=0;
int i=0;
//开始逐一生成题目中的数值和符合
for(i=0;i<=operatornum;i++) {
int fs=0;
fz[i]=random.nextInt(range-1)+1;
fm[i]=random.nextInt(range);
int fz1=fz[i];
int fm1=fm[i];
if(fm[i]!=0&&fm[i]!=1) {
if(fz[i]>fm[i] && fz[i]%fm[i]!=0) {
fs=fz[i]/fm[i];
fz1=fz[i]%fm[i];
}
int[]fzfm=disposeFS(fz1,fm[i]);
fz1=fzfm[0];
fm1=fzfm[1];
if(fs!=0&&fz1!=fm1) {
exer=exer+String.valueOf(fs)+"'"+String.valueOf(fz1)+"/"+String.valueOf(fm1);
}else if(fs==0&&fz1!=fm1&&fm1!=1){
exer=exer+String.valueOf(fz1)+"/"+String.valueOf(fm1);
}else if(fz1>=fm1&&fz1%fm1==0) {
exer=exer+String.valueOf(fz1/fm1);
}else if(fs==0&&fm1==1) {
exer=exer+String.valueOf(fz1);
}
int op=random.nextInt(4);
operator[i]=produceop(op);
exer=exer+" "+operator[i]+" ";
}else if(fm[i]==1||fm[i]==0) {
exer=exer+String.valueOf(fz[i]);
int op=random.nextInt(4);
operator[i]=produceop(op);
exer=exer+" "+operator[i]+" ";
}
}
fz[i]=random.nextInt(range-1)+1;
fm[i]=random.nextInt(range-1)+1;
int fs=0;
int fz1=fz[i];
int fm1=fm[i];
if(fm[i]!=0&&fm[i]!=1) {
if(fz[i]>fm[i]&&fz[i]%fm[i]!=0) {
fs=fz[i]/fm[i];
fz1=fz[i]%fm[i];
}
int[]fzfm=disposeFS(fz1,fm1);
fz1=fzfm[0];
fm1=fzfm[1];
if(fs!=0&&fz1!=fm1) {
exer=exer+String.valueOf(fs)+"'"+String.valueOf(fz1)+"/"+String.valueOf(fm1);
}else if(fs==0&&fz1!=fm1&&fm1!=1){
exer=exer+String.valueOf(fz1)+"/"+String.valueOf(fm1);
}else if(fz1>=fm1&&fz1%fm1==0) {
exer=exer+String.valueOf(fz1/fm1);
}else if(fs==0&&fm1==1) {
exer=exer+String.valueOf(fz1);
}
}else if(fm1==0||fm1==1){
exer=exer+String.valueOf(fz[i]);
}
exer=exer+" = ";//题目生成完成
//对生成的题目进行答案的计算
int[] nefz= new int[operatornum+2];
int[] nefm= new int[operatornum+2];
String[] neop= new String[operatornum+1];
int opk=0;
//对题目进行处理,将乘法和除法优先计算
if(operator[0]=="+"||operator[0]=="-") {
nefz[0]=fz[0];
nefm[0]=fm[0];
neop[0]=operator[0];
opk++;
}else if(operator[0]=="x") {
nefz[0]=mul(fz[0],fz[1],fm[0],fm[1])[0];
nefm[0]=mul(fz[0],fz[1],fm[0],fm[1])[1];
}else if(operator[0]=="÷") {
nefz[0]=div(fz[0],fz[1],fm[0],fm[1])[0];
nefm[0]=div(fz[0],fz[1],fm[0],fm[1])[1];
}
int k=1;
for(int j=1;j<operator.length;j++) {
if(operator[j]=="+"||operator[j]=="-") {
if(operator[j-1]=="+"||operator[j-1]=="-") {
nefz[k]=fz[j];
nefm[k]=fm[j];
neop[opk]=operator[j];
k++;
opk++;
}else if(operator[j-1]=="x"||operator[j-1]=="÷") {
neop[opk]=operator[j];
opk++;
}
}else if(operator[j]=="x") {
if(operator[j-1]=="+"||operator[j-1]=="-") {
nefz[k]=mul(fz[j],fz[j+1],fm[j],fm[j+1])[0];
nefm[k]=mul(fz[j],fz[j+1],fm[j],fm[j+1])[1];
k++;
}else if(operator[j-1]=="x"||operator[j-1]=="÷"){
nefz[k]=mul(nefz[k-1],fz[j+1],nefm[k-1],fm[j+1])[0];
nefm[k]=mul(nefz[k-1],fz[j+1],nefm[k-1],fm[j+1])[1];
k++;
}
}else if(operator[j]=="÷") {
if(operator[j-1]=="+"||operator[j-1]=="-") {
nefz[k]=div(fz[j],fz[j+1],fm[j],fm[j+1])[0];
nefm[k]=div(fz[j],fz[j+1],fm[j],fm[j+1])[1];
k++;
}else if(operator[j-1]=="x"||operator[j-1]=="÷"){
nefz[k]=div(nefz[k-1],fz[j+1],nefm[k-1],fm[j+1])[0];
nefm[k]=div(nefz[k-1],fz[j+1],nefm[k-1],fm[j+1])[1];
k++;
}
}
}
int j=operator.length;
if(operator[j-1]=="+"||operator[j-1]=="-") {
nefz[k]=fz[j];
nefm[k]=fm[j];
neop[k-1]=operator[j-1];
}
//计算加法和减法,得出答案
int anfz=nefz[0];
int anfm=nefm[0];
int anfs=0;
if(neop[0]!=null) {
for(int t=0;t<neop.length;t++) {
if(neop[t]=="+") {
int tanfzfm[]=add(anfz,nefz[t+1],anfm,nefm[t+1]);
anfz=tanfzfm[0];
anfm=tanfzfm[1];
}else if(neop[t]=="-") {
ifne=judgeM(anfz,nefz[t+1],anfm,nefm[t+1]);
int tanfzfm[]=sub(anfz,nefz[t+1],anfm,nefm[t+1]);
anfz=tanfzfm[0];
anfm=tanfzfm[1];
}
}
}else {
anfz=nefz[k-1];
anfm=nefm[k-1];
}
//对答案进行约分等处理,并写入答案字符串
int insfz[]=disposeFS(anfz,anfm);
anfz=insfz[0];
anfm=insfz[1];
if(anfz>0) {
if(anfm!=1&&anfm!=0) {
if(anfz>anfm&&anfz%anfm!=0) {
anfs=anfz/anfm;
anfz=anfz%anfm;
answ=String.valueOf(anfs)+"'"+String.valueOf(anfz)+"/"+String.valueOf(anfm);
}else if(anfz%anfm==0) {
answ=String.valueOf(anfz/anfm);
}else if(anfz<anfm) {
answ=String.valueOf(anfz)+"/"+String.valueOf(anfm);
}
}else if(anfm==1){
answ=String.valueOf(anfz);
}
}else if(anfz==0||anfm==0){
answ="0";
}
return new exercisepro (exer,answ,ifne);
}
通过random随机生成分子和分母,若随机生成的分母为1则生成的为整数,将生成的分子和分母存入数组,对假分数进行判断,将假分数化为真分数,通过生成随机数,将数字与符号对应生成符号,并存入符号的字符串数组。遍历字符串数组,优先计算乘除并将答案存入数组,对题目进行处理后留下加减运算符号存入新的符号数组,对只有加减的式子进行运算,对得到的答案进行约分处理并写成规定的形式写入答案数组。
五、测试运行
测试代码:
点击查看代码
public class Myapp_test {
@Test
public void test1() {
String[] args= {"-n","10","-r","10000"};
Myapp.main(args);
System.out.println("第一个测试结束");
}
@Test
public void test2() {
String[] args= {"-e","10","-r","10"};
Myapp.main(args);
System.out.println("第二个测试结束");
}
@Test
public void test3() {
String[] args= {"-n","-1","-r","10"};
Myapp.main(args);
System.out.println("第三个测试结束");
}
@Test
public void test4() {
String[] args= {"-n","10","-r","20000"};
Myapp.main(args);
System.out.println("第四个测试结束");
}
@Test
public void test5() {
String[] args= {"-r","20000","-n","10"};
Myapp.main(args);
System.out.println("五个测试结束");
}
@Test
public void test6() {
String[] args= {"-n","10","-n","10"};
Myapp.main(args);
System.out.println("第六个测试结束");
}
@Test
public void test7() {
String[] args= {"-r","10","-e","10"};
Myapp.main(args);
System.out.println("第七个测试结束");
}
@Test
public void test8() {
String[] args= {"-r","10","-n","-1"};
Myapp.main(args);
System.out.println("第八个测试结束");
}
@Test
public void test9() {
String[] args= {"-r","10000","-n","10"};
Myapp.main(args);
System.out.println("第九个测试结束");
}
}
测试结果:
测试覆盖率:
除了File_IO中写入文件失败的情况没有进行测试,其他代码基本上有所覆盖
六、项目小结
本次作业写的比较赶所以关键函数写的比较冗杂,也可能有部分功能重复或多余,但由于代码写的比较冗杂难以判断功能是否需要,同时需求九也没有足够的时间完成,下次希望能够在时间充足的情况下充分分析并完成所有需求,考虑更精简易懂的代码结构
虽然本作业由我独自完成,但如果通过结对完成,可以节省很多个人的精力,在测试时也能发现更多写代码的人意识不到的问题和漏洞,同时也会有人共同对代码设计提出意见。