postfixcalc函数 java_结对编程--四则运算(Java)萧英杰 夏浚杰

结对编程--四则运算(Java)萧英杰 夏浚杰

功能要求

题目:实现一个自动生成小学四则运算题目的命令行程序

使用 -n 参数控制生成题目的个数(实现)

使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息(实现)

生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1 − e2的子表达式,那么e1 ≥ e2 (实现)

生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数 (实现)

每道题目中出现的运算符个数不超过3个 (实现)

程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。3+(2+1)和1+2+3这两个题目是重复的,由于+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。生成的题目存入执行程序的当前目录下的Exercises.txt文件 (实现)

在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件 (实现)

程序应能支持一万道题目的生成 (实现)

程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,统计结果输出到文件Grade.txt (实现)

PSP

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

60

90

· Estimate

· 估计这个任务需要多少时间

60

90

Development

开发

1920

2270

· Analysis

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

200

250

· Design Spec

· 生成设计文档

50

60

· Design Review

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

20

20

· Coding Standard

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

10

10

· Design

· 具体设计

30

40

· Coding

· 具体编码

1500

1800

· Code Review

· 代码复审

50

30

· Test

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

60

60

Reporting

报告

100

100

· Test Report

· 测试报告

60

60

· Size Measurement

· 计算工作量

10

10

· Postmortem & Process Improvement Plan

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

30

30

合计

2080

2460

效能分析

编码过程中,在表达式生成和查重方面花费了很多时间,对于查重,需要将已经生成的表达式加入到一个集合里,原本想用数组存放查重表达式,后来发现此方案效率偏低,之后在网上查找了一些资料后,采用HashMap存放,使用containsKey()进行查重。经过测试,该方案优于原方案。此外,还对代码进行了一定程度上的优化,使代码更加简洁,效率提高。

设计实现过程

1.操作数的生成

题目要求生成的操作数可以是自然数、分数,由于整数可以看成分母为1的分数,所以将整数化作分数进行计算。因此设计了一个分数类用于分数的定义,存放,计算和输出。

2.表达式的生成和计算

经过查询资料和讨论之后,我们决定用fraction_create方法和operator_create方法随机生成几个操作数和运算符,将它们按规则组成表达式。至于表达式的计算,生成的表达式是中缀表达式,我们将它转换为后缀表达式,并calculate方法计算,得出答案。

db98d9d507ddbae0623a0692d3e80018.png

代码说明

Fraction类:分数的的定义,存放,计算和输出

package myapp;

public class Fraction {

//分子

private int a;

//分母

private int b;

//分数

public Fraction(int a, int b) {

this.a = a;

if (b == 0) {

throw new ArithmeticException("分母不能为零");

} else {

this.b = b;

}

simple();

}

//化简

private Fraction simple() {

int gcd = this.gcd(this.a, this.b);

this.a /= gcd;

this.b /= gcd;

return this;

}

//最大公约数

private int gcd(int a, int b) {

int mod = a % b;

if (mod == 0) {

return b;

} else {

return gcd(b, mod);

}

}

//四则运算

public Fraction add(Fraction second) {//加法

return new Fraction(this.a * second.b + second.a * this.b,

this.b * second.b);

}

public Fraction sub(Fraction second) {//减法

return new Fraction(this.a * second.b - second.a * this.b,

this.b * second.b);

}

public Fraction mult(Fraction second) {//乘法

return new Fraction(this.a*second.a,

this.b * second.b);

}

public Fraction div(Fraction second) {//除法

return new Fraction(this.a*second.b,

this.b * second.a);

}

//分数类转字符串类型

public String toString() {

if (this.b==1) {

return String.valueOf(a);

}

else if(this.a>this.b) {

int c=0;

c=this.a/this.b;

this.a=this.a%this.b;

return String.valueOf(c)+"'"+String.valueOf(a)+"/"+String.valueOf(b);

}

else{

return String.valueOf(a)+"/"+String.valueOf(b);}

}

public static Fraction tofraction(String str) {

str=str.replaceAll(" ", "");

int a=1;

int b=1;

int s1=str.indexOf("'");

int s2=str.indexOf("/");

if(s1!=-1) {

int c=Integer.valueOf(str.substring(0,s1));

b=Integer.valueOf(str.substring(s2+1));

a=c*b+Integer.valueOf(str.substring(s1+1,s2));

} else if(s2!=-1) {

b=Integer.valueOf(str.substring(s2+1));

a=Integer.valueOf(str.substring(0,s2));

} else {

a=Integer.valueOf(str);

b=1;

}

return new Fraction(a,b);

}

//比较大小,比较此分数是否大于输入分数

public boolean isgreaterthan2(Fraction f) {

int z=this.a * f.b - f.a * this.b;

if(z>0) {return true;}

else return false;

}

public boolean isZero() {

return a == 0;

}

}

Expression类:表达式的生成

package myapp;

import java.util.Random;

public class Expression {

Random random=new Random();

Calc c=new Calc();

//随机生成一个分数

public Fraction fraction_create(int r) {

int choose=random.nextInt(2)+1;

int denominator=1;

int numerator=0;

if(choose==1) { //整数

numerator=random.nextInt(r);

denominator=1;

}else {

denominator=random.nextInt(r)+1;

numerator=random.nextInt(r*r+1);

while(numerator/denominator>=r) {

denominator=random.nextInt(r)+1;

numerator=random.nextInt(r+1);}

}

return new Fraction( numerator , denominator );

}

//随机生成运算符

public char operator_create() {

int oper=random.nextInt(4);

char sign;

switch (oper) {

case 0:

sign='+';

break;

case 1:

sign='-';

break;

case 2:

sign='×';

break;

case 3:

sign='÷';

break;

default:

sign='+';

}

return sign;

}

//生成表达式

public String getexp(int r) {

String expression="";

int ran=random.nextInt(3);

switch (ran) {

case 0:

expression=oneopexp(r);

break;

case 1:

expression=twoopexp(r);

break;

case 2:

expression=threeopexp(r);

break;

}

return expression;

}

//一个运算符

public String oneopexp(int r) {

Fraction f1=fraction_create(r);

Fraction f2=fraction_create(r);

char op=operator_create();

String exp ="";

switch (op) {

case '+':

exp= f1+" + "+f2;

break;

case '-':

if(!f1.isgreaterthan2(f2)) {

Fraction temp;

temp=f1;f1=f2;f2=temp;

}

exp= f1+" - "+f2;

break;

case '×':

exp= f1+" × "+f2;

break;

case '÷':

while(f2.isZero()) {

f2=fraction_create(r);

}

exp= f1+" ÷ "+f2;

break;

}

return exp;

}

//两个运算符

public String twoopexp(int r){

Fraction f1=fraction_create(r);

Fraction f2=fraction_create(r);

Fraction f3=fraction_create(r);

char op1=operator_create();

char op2=operator_create();

String exp ="";

String exp1="";

switch (op1) {

case '+':

exp= f1+" + "+f2;

break;

case '-':

if(!f1.isgreaterthan2(f2)) {

Fraction temp;

temp=f1;f1=f2;f2=temp;

}

exp= f1+" - "+f2;

break;

case '×':

exp= f1+" × "+f2;

break;

case '÷':

while(f2.isZero()) {

f2=fraction_create(r);

}

exp= f1+" ÷ "+f2;

break;

}

switch (op2) {

case '+':

exp1=exp+" + "+f3;

break;

case '-':

if(!c.calculate(exp).isgreaterthan2(f3)) {

exp1= f3+" - "+"("+exp+")";

}else {

exp1= exp+" - "+f3;}

break;

case '×':

exp1= "("+exp+")"+" × "+f3;

break;

case '÷':

while(f3.isZero()) {

f3=fraction_create(r);

}

exp1="("+exp+")"+" ÷ "+f3;

break;

}

return exp1;

}

//三个运算符改

public String threeopexp(int r){

Fraction f1=fraction_create(r);

Fraction f2=fraction_create(r);

Fraction f3=fraction_create(r);

Fraction f4=fraction_create(r);

char op1=operator_create();

char op2=operator_create();

char op3=operator_create();

String exp ="";

String exp1="";

String exp2="";

switch (op1) {

case '+':

exp= f1+" + "+f2;

break;

case '-':

if(!f1.isgreaterthan2(f2)) {

Fraction temp;

temp=f1;f1=f2;f2=temp;

}

exp= f1+" - "+f2;

break;

case '×':

exp= f1+" × "+f2;

break;

case '÷':

while(f2.isZero()) {

f2=fraction_create(r);

}

exp= f1+" ÷ "+f2;

break;

}

switch (op2) {

case '+':

exp1=exp+" + "+f3;

break;

case '-':

if(!c.calculate(exp).isgreaterthan2(f3)) {

exp1= f3+" - "+"("+exp+")";

}else {

exp1= exp+" - "+f3;}

break;

case '×':

exp1= "("+exp+")"+" × "+f3;

break;

case '÷':

while(f3.isZero()) {

f3=fraction_create(r);

}

exp1="("+exp+")"+" ÷ "+f3;

break;

}

switch (op3) {

case '+':

exp2=exp1+" + "+f4;

break;

case '-':

if(!c.calculate(exp1).isgreaterthan2(f4)) {

exp2= f4+" - "+"("+exp1+")";

}else {

exp2= exp1+" - "+f4;}

break;

case '×':

exp2= "("+exp1+")"+" × "+f4;

break;

case '÷':

while(f4.isZero()) {

f4=fraction_create(r);

}

exp2="("+exp1+")"+" ÷ "+f4;

break;

}

return exp2;

}

}

Calc类:中缀表达式转后缀表达式并计算,查重表达式的生成

package myapp;

import java.util.ArrayList;

import java.util.List;

import java.util.Stack;

public class Calc {

char[] oper6= {'+','-','×','÷','(',')'};

String[] oper4={"+","-","×","÷"};

private static int ADDITION=1;

private static int SUBTRACTION=1;

private static int MULTIPLICATION=2;

private static int DIVISION=2;

public static int getValue(String op){

int value;

switch (op){

case "+":

value=ADDITION;

break;

case "-":

value=SUBTRACTION;

break;

case "×":

value=MULTIPLICATION;

break;

case "÷":

value=DIVISION;

break;

default:

value=0;

}

return value;

}

//判断是否是操作符

public boolean isoper(char c) {

for(char op:oper6) {

if(op==c) return true;

}

return false;

}

public boolean isoper(String s) {

for(String op1:oper4) {

if(s.equals(op1)) return true;

}

return false;

}

//判断是否是数字

public boolean isfra(char c) {

if(c>='0'&&c<='9')

{return true;}

return false;

}

public boolean isfraop(char c) {

if(c=='\''||c=='/') {

return true;

}

return false;

}

//将String类型表达式转换成List类型

public List Stringtolist(String str){

List infix = new ArrayList();

str=str.replace(" ", "");

char op;

String temp="";

for(int i=0;i

op=str.charAt(i);

if(isfra(op)||isfraop(op)) {

temp+=op;

} else if(isoper(op)) {

if(!temp.isEmpty()) {

infix.add(temp);

temp="";

}

infix.add(op+"");

}

}

if(!temp.isEmpty()) {

infix.add(temp);

temp="";

}

return infix;

}

//将中缀表达式转换为后缀表达式

public List infixtopostfix(List infix){

List postfix=new ArrayList();

Stack s1=new Stack();

for (String str : infix) {

if(str.equals("(")) {

s1.push(str);

}

else if(str.equals(")")) {

while(!s1.peek().equals("(")) {

postfix.add(s1.pop());

}

s1.pop();

}

else if(str.equals("+")||str.equals("-")||str.equals("×")||str.equals("÷")) {

while (s1.size() != 0 && getValue(s1.peek()) >= getValue(str)) {

postfix.add(s1.pop());

}

s1.push(str);

} else {

postfix.add(str);

}

}

while (s1.size() != 0) {

postfix.add(s1.pop());

}

return postfix;

}

//对后缀表达式进行计算

public Fraction calculate(String str) {

List linfix=Stringtolist(str);

List lpostfix=infixtopostfix(linfix);

Stack s2=new Stack();

Fraction f1;

Fraction f2;

Fraction answer;

for(String cal:lpostfix) {

if(!isoper(cal)) {

Fraction f=Fraction.tofraction(cal);

s2.push(f);

} else {

switch (cal) {

case "+":

f1=s2.pop();

f2=s2.pop();

answer=f2.add(f1);

s2.push(answer);

break;

case "-":

f1=s2.pop();

f2=s2.pop();

answer=f2.sub(f1);

s2.push(answer);

break;

case "×":

f1=s2.pop();

f2=s2.pop();

answer=f2.mult(f1);

s2.push(answer);

break;

case "÷":

f1=s2.pop();

f2=s2.pop();

answer=f2.div(f1);

s2.push(answer);

break;

}

}

}

return s2.pop();

}

//查重表达式的生成

public List getcnki(String str){

List linfix=Stringtolist(str);

List lpostfix=infixtopostfix(linfix);

List cnkiexp=new ArrayList();

Stack st=new Stack();

String top1=null;

String top2=null;

for(String cal:lpostfix) {

if(!isoper(cal)) {

st.push(cal);

} else if(cal.equals("+")||cal.equals("-")||cal.equals("×")) {

cnkiexp.add(cal);

top1=st.pop();

top2=st.pop();

if(top2!="@") {

cnkiexp.add(top2);

}

if(top1!="@") {

cnkiexp.add(top1);

}

st.push("@");

}

else if(cal.equals("÷")) {

cnkiexp.add(cal);

top1=st.pop();

top2=st.pop();

cnkiexp.add(top2);

cnkiexp.add(top1);

st.push("@");

}

}

return cnkiexp;

}

//将List类型表达式转换成String类型

public String list2String(List list) {

String str1="";

for(String s:list) {

str1=str1+s+" ";

}

return str1;

}

}

Create类:题目和答案文档的生成

package myapp;

import java.io.*;

import java.util.HashMap;

import java.util.List;

public class Create {

Expression expression=new Expression();

Calc cal=new Calc();

HashMap map = new HashMap();

//在当前目录下生成练习题和答案

public void cr(int n,int r) throws IOException {

BufferedWriter btex=new BufferedWriter(new FileWriter(".\\Exercises.txt"));

BufferedWriter btan=new BufferedWriter(new FileWriter(".\\Answers.txt"));

for(int i=1;i

String exps=expression.getexp(r);

List cnkiexp1=cal.getcnki(exps);

String cnki1=cal.list2String(cnkiexp1);

boolean contains2 =false;

if(cnkiexp1.get(0).equals("+")||cnkiexp1.get(0).equals("×")) {

List cnkiexp2=cnkiexp1;

String t1=cnkiexp2.get(1);

String t2=cnkiexp2.get(2);

cnkiexp2.set(1, t2);

cnkiexp2.set(2, t1);

String cnki2=cal.list2String(cnkiexp2);

contains2 = map.containsKey(cnki2);

}

if(i==1) {map.put(cnki1,"");}

boolean contains = map.containsKey(cnki1);

if(contains==true||contains2==true) {

exps=expression.getexp(r);

cnkiexp1=cal.getcnki(exps);

cnki1=cal.list2String(cnkiexp1);

contains2 =false;

if(cnkiexp1.get(0).equals("+")||cnkiexp1.get(0).equals("×")) {

List cnkiexp2=cnkiexp1;

String t1=cnkiexp2.get(1);

String t2=cnkiexp2.get(2);

cnkiexp2.set(1, t2);

cnkiexp2.set(2, t1);

String cnki2=cal.list2String(cnkiexp2);

contains2 = map.containsKey(cnki2);

}

}

map.put(cnki1,"");

Fraction answer=cal.calculate(exps);

String answers=answer.toString();

btex.write(i+". "+exps+"\r\n");

btan.write(i+". "+answers+"\r\n");

}

btex.flush();

btan.flush();

btex.close();

btan.close();

}

}

Checkanswer:批改答卷

package myapp;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

public class Checkanswer {

public void check(String expath,String anpath) throws IOException{

BufferedReader brex=new BufferedReader(new FileReader(expath));

BufferedReader bran=new BufferedReader(new FileReader(anpath));

BufferedWriter bwgrade=new BufferedWriter(new FileWriter(".\\Grade.txt"));

List Correct=new ArrayList();

List Wrong=new ArrayList();

String an=null;

String ex=null;

while((an=bran.readLine())!=null) {

ex=brex.readLine();

int point=an.indexOf(".");

String stran=an.substring(point+1);

stran=stran.trim();

String strex=ex.substring(point+1);

strex=strex.trim();

if(stran.equals(strex)) {

String cno=an.substring(0, point);

Correct.add(cno);

}else {

String wno=an.substring(0, point);

Wrong.add(wno);

}

}

String corr=String.join(",",Correct);

String wr=String.join(",",Wrong);

bwgrade.write("Correct: "+Correct.size()+" ("+corr+")"+"\r\n");

bwgrade.write("Wrong: "+Wrong.size()+" ("+wr+")");

bwgrade.flush();

bwgrade.close();

}

}

Run:主函数类,对输入命令进行处理,调用相应的方法

package myapp;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.util.Scanner;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public class Run {

public static void main(String[] args) throws IOException {

Scanner scan=new Scanner(System.in);

String command=null;

Create create=new Create();

Checkanswer checkanswer=new Checkanswer();

String nr="^\\-n\\s+\\d+\\s+\\-r\\s+\\d+$||^\\-r\\s+\\d+\\s+\\-n\\s+\\d+$";

String ea="^\\-e\\s+\\S+\\s+\\-a\\s+\\S+$";

int n = 0;

int r = 0;

String exercisesfile=null;

String answersfile=null;

System.out.println("小学四则运算题目生成程序");

System.out.println("-r 题目中数值(该参数可以设置为1或其他自然数)");

System.out.println("-n 题目个值(该参数可以设置为1或其他自然数)");

System.out.println("-e 需要批改的答案的文件路径");

System.out.println("-a 正确答案的文件路径");

System.out.println("请按照下面的格式输入命令");

System.out.println("例:-n 10 -r 10 或 -r 10 -n 10 (-r和-n命令需要一起使用)");

System.out.println("例:-e D:\\\\myanswer.txt -a D:\\\\Answers.txt (-e和-a命令需要一起使用)");

while(scan.hasNextLine()) {

if (scan.hasNextLine()) {

command = scan.nextLine();}

//检查命令是否正确

Pattern pa = Pattern.compile(nr);

Matcher ma = pa.matcher(command);

Pattern p = Pattern.compile(ea);

Matcher m = p.matcher(command);

if(!(ma.matches()||m.matches())) {

System.out.println("命令格式错误,请重新输入");

continue;

}

//对命令进行分割

String[] c=command.split("\\s+");

if(c[0].equals("-n")&&c[2].equals("-r")) {

n=Integer.parseInt(c[1]);

r=Integer.parseInt(c[3]);

create.cr(n,r);

System.out.println("练习题目Exercises.txt和答案文件Answers.txt已生成,放置在本程序的当前目录下");

}

else if(c[0].equals("-r")&&c[2].equals("-n")){

r=Integer.parseInt(c[1]);

n=Integer.parseInt(c[3]);

create.cr(n,r);

System.out.println("练习题目Exercises.txt和答案文件Answers.txt已生成,放置在本程序的当前目录下");

}

if(c[0].equals("-e")&&c[2].equals("-a")) {

exercisesfile=c[1];

answersfile=c[3];

try {

checkanswer.check(exercisesfile,answersfile);}

catch(FileNotFoundException e) {

System.out.println("找不到指定文件,请重新输入正确的文件路径");

continue;

}

System.out.println("批改文件Grade.txt已生成,放置在本程序的当前目录下");

}

System.out.println("请及时保存文件,再次使用程序时上一次生成的文件会被覆盖");

//归零

n=0;

r=0;

}

}

}

测试运行

生成10道题目:

28be60a869e5e2305cb830dfb2c149fa.png

a662a4d749a12d2a05e09c98b3745e3f.png

统计答案中对错的的数目:

31d810d2940ae14d24fe54974e277c9c.png

e3294d1b101ca56db1d721623f3e96a5.png

生成10000题目:

381bfa7f08a045b7962822d67419fadf.png

项目小结

此次项目,由我和夏浚杰同学一起结对编程,我们各负责一部分代码的编写。我们在设计功能时会提出各自的想法,经过讨论选择更合适的方法。在结对编程之后,我感受到了结对编程的优点在于,在我编写代码的过程中,夏浚杰同学会在旁边找出我的错误,让我能及时修改代码,这样提高了编程效率,节约时间。在结对编程中,夏浚杰同学提出了不同的想法,让我有所收获。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值