github地址:https://github.com/IMFatDragon/sizeyunsuan.git
完成者:
周惠龙 3117004638
陈浩峰 3117004603
- 使用 -n 参数控制生成题目的个数,例如 SiZeYunSuan.exe -n 10 将生成10个题目。(完成)
- 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如SiZeYunSuan.exe -r 10 将生成10以内(不包括10)的四则运算题目。(完成)
- 生成的题目中计算过程不能产生负数,即算术表达式中如果存在形如e1 − e2的子表达式,必须e1 ≥ e2。(完成)
- 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。(完成)
- 每道题目中出现的运算符个数不超过3个。(完成)
- 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。(完成)
- 生成的题目存入执行程序的当前目录下的Exercises.txt文件,格式如下:(完成)
- 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:(完成)
- 程序应能支持一万道题目的生成(完成)
- 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:(未完成)
- 表达式生成模块:表达式包括运算符部分(加减乘除)、数字部分(自然数,真分数,带分数)、括号部分。数值部分利用random对象的nextInt方法随机从1开始生成,其中分子随机数的数值范围是比分母小1,保证生成的数字不出现假分数的情况;运算符的个数是利用函数随机生成1-3之间的自然数,加减乘除的符号也是利用随机数1-4来生成;符号部分利用next Boolean方法根据true或者false来决定括号的生成,该过程中利用一个变量来标记括号范围。
- 表达式运算模块:上述模块生成的表达式只是初步的表达式,运算功能是利用后缀表达式来实现的,生成后缀表达式后再将表达式的所有数值转化为分数形式,统一方便计算。为保证该过程中不出现负数运算,凡是进行减法运算的操作,都会对运算结果进行检验,一旦出现负数则丢弃当前表达式,直到再次生成的表达式符合要求,同时在此过程进行表达式的重复判断,将每一个当前非负表达式与已生成表达式进行查重检验,满足条件则加入Arraylist中,同时保存运算结果。
- 查重检验:将后缀表达式转换为查重表达式,查重表达式的结果为运算符在先,后面跟着该运算符的操作数,例如(1+2)*3-4,后缀表达式为:12+3*4-,按照查重表达式的结构为:+12*3-4,查重过程中只需要判断查重表达式是否一致,或者在查重表达式中第一个字符'+'或'*'的情况下后续的两个操作数交换位置后是否一致即可。也就是说+12*3-4与+21*3-4的表达式是一致的。举个表达式不重复的例子:1+2+3和3+2+1,查重表达式分别为+12+3和+32+1,查重表达式不相同,即使交换'+'后面的两个操作数也无法一致,故这两个表达式不重复。
- 运算结果检验模块:将最终符合要求的表达式存入当前目录下的Question.txt文件,正确答案保存在Answer.txt文件中,并对运算结果进行检。


1 package Calculation;
2
3 import java.util.ArrayList;
4 import java.util.Random;
5 import java.util.Scanner;
6
7
8 public class Ran_Expression { //随机生成初步的表达式
9
10
11
12 public static char[] ysf={'+','-','*','÷'};
13 public static String exp_str;//四则运算表达式
14
15 //获取输入
16 public static String getScanner(){
17 Scanner scan=new Scanner(System.in);
18 String input=scan.nextLine();
19 scan.close();
20 return input;
21 }
22
23
24 //随机获取运算符+ - * ÷
25 public static char getysf(){
26 Random ran=new Random();
27 int ysfNum=ran.nextInt(4);
28 return ysf[ysfNum];
29 }
30
31 /**
32 * 获取操作数
33 * @param range 数值范围
34 * @return
35 */
36 public static String getNumber(int range){
37 Random ran=new Random();
38 int index=ran.nextInt(3);
39 String num="";
40
41 /**
42 * 随机获取数字,0获取自然数,1获取真分数,2获取带分数
43 */
44 if(index==0){//自然数
45 Random ran0=new Random();
46 num=ran0.nextInt(range-1)+1+"";
47 }
48 if(index==1){//真分数
49 Random ran1=new Random();
50 int fenmu=ran1.nextInt(range-2)+2;//分母[2,range)
51 int fenzi=ran1.nextInt(fenmu-1)+1;//分子
52 num=fenzi+"/"+fenmu+"";
53 }
54 if(index==2){//带分数
55 Random ran2=new Random();
56 int leftNum=ran2.nextInt(range-1)+1;//左整数部分
57 int rightFM=ran2.nextInt(range-2)+2;//右真分数部分-分母[2,range)
58 int rightFZ=ran2.nextInt(rightFM-1)+1;//右真分数部分-分子
59 num=leftNum+"'"+rightFZ+"/"+rightFM+"";
60 }
61 return num;
62 }
63
64 /**
65 * 去表达式最前和最后的括号
66 * @param str表达式
67 * @return
68 */
69 public static String deleteKuoHao(String str){
70 if((str.substring(0, 1).equals("(")) && (str.substring(str.length()-1).equals(")"))){
71 str=str.substring(1, str.length()-1);
72 }
73 return str;
74 }
75
76
77 //生成四则运算表达式
78 //range题目中操作数的范围
79 public static ArrayList<String> creatAc(int range){
80 Random ran4=new Random();
81 ArrayList<String> list=new ArrayList<String>();//存放每个表达式中的运算符和操作数
82 boolean zuoKuoHao=false;//左括号
83 boolean youKuoHao=false;//右括号
84 boolean tem=false;
85 int ysfNum=ran4.nextInt(3)+1;//每个表达式运算符个数1-3个
86 exp_str="";
87
88 //------------开始生成--------------
89 for(int j=0;j<ysfNum;j++){
90
91 //决定是否加入左括号
92 if(!zuoKuoHao && ran4.nextBoolean()){
93 exp_str+="(";
94 list.add("(");
95 zuoKuoHao=true;
96 }
97 String sz1=getNumber(range);
98 exp_str+=sz1;
99 list.add(sz1);
100 //决定是否加入右括号
101 if(zuoKuoHao && !youKuoHao && tem){
102 if(ran4.nextBoolean()){
103 exp_str+=")";
104 list.add(")");
105 youKuoHao=true;
106 }
107 }
108 char char1=getysf();
109 exp_str+=char1;
110 list.add(char1+"");
111 if(zuoKuoHao){
112 tem=true;
113 }
114 }
115 String sz2=getNumber(range);
116 exp_str+=sz2;
117 list.add(sz2);
118 if(zuoKuoHao && !youKuoHao){
119 exp_str+=")";
120 list.add(")");
121 }
122 exp_str=deleteKuoHao(exp_str);//去掉开头和结尾均为括号
123 //------------结束生成--------------
124
125 System.out.println("生成中,请稍等:"+exp_str);
126 return list;
127
128 }
129
130
131
132 }
1 package Calculation;
2
3 import java.util.ArrayList;
4 import java.util.Stack;
5
6
7 public class After_Expression { //生成后缀表达式
8 /**
9 * 将中序表达式转换成后序表达式
10 * @param str 生成的中序表达式
11 */
12 public static Stack<String> toAfter_Expression(ArrayList<String> list){
13 Stack<String> stack=new Stack<String>();//栈
14 Stack<String> right=new Stack<String>();//右序表达式
15 String ysf;//运算符
16
17 for(int i=0;i<list.size();i++){
18 String ch=list.get(i);
19 if(isysf(ch)){//当前字符为运算符
20 if(stack.empty()==true || ch=="("){//栈为空或者为(直接入栈
21 stack.push(ch);
22 }else{//非栈空、非左括号
23 if(ch==")"){//如果为)
24 while(true){//将(后的运算符出栈并加到后续表达式中
25 if((!stack.empty()) && (!stack.peek().equals("("))){
26 ysf=stack.pop();
27 right.push(ysf);
28 }else{
29 if(!stack.empty())//如果栈顶元素为(
30 stack.pop();
31 break;
32 }
33 }
34 }else{//非栈空、非左括号、非右括号
35 while(true){//栈不为空,优先级低
36 if(!stack.empty() && priority(ch,stack.peek())){
37 ysf=stack.pop()+"";
38 if(!ysf.equals("(")){
39 right.push(ysf);
40 }
41 }else{
42 break;
43 }
44 }
45 stack.push(ch+"");
46 }
47 }
48
49 }else{
50 right.push(ch+"");//操作数
51 }
52 }
53 while(!stack.empty()){
54 ysf=stack.pop()+"";
55 if(!ysf.equals("("))
56 right.push(ysf);
57 }
58 return right;
59 }
60
61
62 // 判断是否为运算符
63 public static boolean isysf(String ch){
64 if((ch.equals("+"))||(ch.equals("-"))||(ch.equals("*"))||(ch.equals("÷"))||(ch.equals("("))||(ch.equals(")")))
65 return true;
66 else
67 return false;
68 }
69
70 /**
71 * 设置运算符的优先级别
72 * @param ysfout当前中序表达式字符
73 * @param ysfin栈中字符
74 * @return
75 */
76 public static boolean priority(String ysfout, String ysfin) {
77 int m = -1, n = -1;
78 String a_ysf[][] = { { "+", "-", "*", "÷", "(", ")" },
79 { "+", "-", "*", "÷", "(", ")" } };
80 int first[][] = { { 1, 1, 2, 2, 2, 0 }, { 1, 1, 2, 2, 2, 0 },
81 { 1, 1, 1, 1, 2, 0 }, { 1, 1, 1, 1, 2, 0 },
82 { 2, 2, 2, 2, 2, 0 }, { 2, 2, 2, 2, 2, 2 } };
83 for (int i = 0; i < 6; i++) {
84 if (ysfin.equalsIgnoreCase(a_ysf[0][i]))
85 m = i;
86 }
87 for (int i = 0; i < 6; i++) {
88 if (ysfout.equalsIgnoreCase(a_ysf[1][i]))
89 n = i;
90 }
91 if (m == -1 && n == -1)
92 return false;
93 else if (m == -1 && n != -1)
94 return false;
95 else if (m != -1 && n == -1)
96 return true;
97 else if (first[m][n] == 1) {
98 return true;
99 } else
100 return false;
101 }
102
103 }
1 package Calculation;
2
3 import java.util.Stack;
4
5 public class CaoZuoShu_handle {
6
7
8 //该类将后续表达式stack转化为有分子分母的后续表达式
9 //存于Calcul_Expression对象的calculatorStack中
10
11 Stack<Calcul_Expression> posfixStack;
12
13 public CaoZuoShu_handle(Stack<String> stack) {
14 Stack<Calcul_Expression> stack1 = new Stack<>();//中间栈
15 Stack<Calcul_Expression> stack2 = new Stack<>();//中间栈
16 while(!stack.isEmpty()){
17 String string = stack.pop();
18 //运算符直接进栈
19 if(string.equals("+")||string.equals("-")||string.equals("*")||string.equals("÷")){
20 Calcul_Expression calcul_exp = new Calcul_Expression(true,string);
21 stack1.push(calcul_exp);
22 }
23 else if(!string.contains("/")){
24 string = string + "/1";
25 Calcul_Expression node = new Calcul_Expression(false,string);
26 stack1.push(node);
27 }
28 else {
29 Calcul_Expression calculator = new Calcul_Expression(false,string);
30 stack1.push(calculator);
31 }
32 }
33 for(Calcul_Expression c:stack1){
34 stack2.push(c);
35 }
36 this.posfixStack = stack2;
37
38 }
39
40
41 }
1 package Calculation;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.Stack;
6
7 public class Calcul_Expression { //计算表达式
8
9
10
11 private static final int String = 0;
12 Integer fenzi;//分子
13 Integer fenmu;//分母
14 boolean isysf;
15 String ysf;
16 Calcul_Expression lChild;
17 Calcul_Expression rChild;
18
19
20 //运算符构造方法
21 public Calcul_Expression(boolean isysf,Integer num,Integer den) {
22 this.isysf = isysf;
23 this.fenmu = den;
24 this.fenzi = num;
25
26 }
27
28 public Calcul_Expression(boolean isysf,String stackElement) {
29 if(isysf == true){//为运算符
30 this.isysf = true;
31 this.ysf = stackElement;
32 }
33 else if (isysf == false && stackElement.contains("'")){//为带分数
34 String[] split1 = stackElement.split("'");
35 String[] split2 = split1[1].split("\\/");
36 this.fenzi = Integer.parseInt(split1[0])*Integer.parseInt(split2[1])
37 + Integer.parseInt(split2[0]);
38 this.fenmu = Integer.parseInt(split2[1]);
39 }
40 else if(isysf == false && (!stackElement.contains("'"))){//为分数
41 String[] s = stackElement.split("\\/");
42 this.fenzi = Integer.parseInt(s[0]);
43 this.fenmu = Integer.parseInt(s[1]);
44 }
45 }
46
47
48
49 public Calcul_Expression() {
50 }
51
52 //根据后缀表达式(分子分母形式)计算
53 //返回运算结果存于stack2中
54 public Stack<Calcul_Expression> calculate(Stack<Calcul_Expression> stackOld){
55 Stack<Calcul_Expression> stack=(Stack<Calcul_Expression>) stackOld.clone();
56 Stack<Calcul_Expression> stack2 = new Stack<>();
57 Calcul_Expression calculator;
58 while(!stack.isEmpty()){
59 if(!(calculator = stack.pop()).isysf){//操作数直接入栈
60 stack2.push(calculator);
61 }
62 else if(calculator.isysf){//若为运算符
63
64 //每次去除栈顶两个元素
65 Calcul_Expression calculator1 = stack2.pop();
66 Calcul_Expression calculator2 = stack2.pop();
67
68 switch (calculator.ysf) {
69 case "+":
70 stack2.push(calculator.add(calculator2, calculator1));
71 break;
72
73 case "-":
74 Calcul_Expression res=calculator.sub(calculator2, calculator1);
75 if(res.fenzi>0){
76 stack2.push(res);
77 }else{
78 res.ysf="#";
79 stack2.push(res);
80 return stack2;
81 }
82 stack2.push(calculator.sub(calculator2, calculator1));
83 break;
84
85 case "*":
86 stack2.push(calculator.mul(calculator2, calculator1));
87 break;
88
89 case "÷":
90 stack2.push(calculator.div(calculator2, calculator1));
91 break;
92
93 default:
94 break;
95 }
96
97 }
98 }
99 return stack2;
100 }
101
102 //加法
103 public Calcul_Expression add(Calcul_Expression calculator1,Calcul_Expression calculator2) {
104 Integer num = calculator1.fenzi*calculator2.fenmu +
105 calculator2.fenzi*calculator1.fenmu;
106 Integer den = calculator1.fenmu*calculator2.fenmu;
107 int g = gcd(num, den);
108 Calcul_Expression calculator = new Calcul_Expression(false, num/g, den/g);
109 return calculator;
110 }
111
112 //减法
113 public Calcul_Expression sub(Calcul_Expression calculator1,Calcul_Expression calculator2) {
114 Integer num = calculator1.fenzi*calculator2.fenmu -
115 calculator2.fenzi*calculator1.fenmu;
116 Integer den = calculator1.fenmu*calculator2.fenmu;
117 int g = gcd(num, den);
118 Calcul_Expression calculator = new Calcul_Expression(false, num/g, den/g);
119 return calculator;
120 }
121
122 //乘法
123 public Calcul_Expression mul(Calcul_Expression calculator1,Calcul_Expression calculator2) {
124 Integer num = calculator1.fenzi*calculator2.fenzi;
125 Integer den = calculator1.fenmu*calculator2.fenmu;
126 int g = gcd(num, den);
127 Calcul_Expression calculator = new Calcul_Expression(false, num/g, den/g);
128 return calculator;
129 }
130
131 //除法
132 public Calcul_Expression div(Calcul_Expression calculator1,Calcul_Expression calculator2) {
133 Integer num = calculator1.fenzi*calculator2.fenmu;
134 Integer den = calculator1.fenmu*calculator2.fenzi;
135 int g = gcd(num, den);
136 Calcul_Expression calculator = new Calcul_Expression(false, num/g, den/g);
137 return calculator;
138 }
139
140 //最大公约数
141 public int gcd(int a, int b){
142 int m = Math.max(Math.abs(a), Math.abs(b));
143 int n = Math.min(Math.abs(a), Math.abs(b));
144 int r;
145 while(n!=0){
146 r = m % n;
147 m = n;
148 n = r;
149 }
150 return m;
151 }
152
153 //比较两个分数数大小
154 /**
155 *
156 * @return f1 > f2 返回 2
157 * f1 = f2返回1
158 * f1 < f2返回-1
159 * 其他 返回0
160 */
161 public int compareFraction(Calcul_Expression f1,Calcul_Expression f2) {
162 Calcul_Expression node = new Calcul_Expression();
163
164 if (f1.isysf||f2.isysf) {
165 System.out.println("请输入数字进行比较!");
166 return 0;
167 }
168 Calcul_Expression compare = node.sub(f1, f2);//f1 - f2 结果为Calcul_Expression类型
169 int result = compare.fenzi/compare.fenmu;//f1 - f2的结果
170 if (result == 0) {
171 return 1;
172 }
173 else if (result > 0) {
174 return 2;
175 }
176 else if (result < 0) {
177 return -1;
178 }
179
180 return 0;
181 }
182
183 /**
184 *
185 * @param o1
186 * @param o2
187 * @return o1 > o2 return 2
188 * o1 = o2 return 1
189 * o1 < o2 return -1
190 * 其他 return 0
191 */
192 public int compareysf(Calcul_Expression o1,Calcul_Expression o2) {
193 if (!o1.isysf||!o2.isysf) {
194 System.out.println("请输入正确运算符!");
195 return 0;
196 }
197 HashMap<String, Integer> priMap = new HashMap<>();
198 priMap.put("+", 0);
199 priMap.put("-", 0);
200 priMap.put("*", 1);
201 priMap.put("÷", 1);
202
203 if (priMap.get(o1.ysf) > priMap.get(o2.ysf)) {
204 //o1 高于 o2
205 return 2;
206 }
207 else if (priMap.get(o1.ysf) == priMap.get(o2.ysf)) {
208 //o1 低于o2
209 return 1;
210 }
211 else if (priMap.get(o1.ysf) < priMap.get(o2.ysf)) {
212 //o1等于o2
213 return 1;
214 }
215 return 0;
216 }
217
218 //假分数转带分数输出
219 public ArrayList<String> imTomix(ArrayList<Calcul_Expression> answerList) {
220 ArrayList<String> arrayList = new ArrayList<>();
221 for (int i = 0; i < answerList.size(); i++) {
222 if (answerList.get(i).isysf) {
223 System.out.println("这个结果算错了!");
224 }
225 else if (answerList.get(i).fenmu == 1){//分母为1,分数= 分子的值
226 arrayList.add(answerList.get(i).fenzi + "");
227 }
228 else if ((answerList.get(i).fenzi == 0) ||(answerList.get(i).fenzi == 0)) {//若分子为0,则分数为0
229 arrayList.add(answerList.get(i).fenzi + "");
230 }
231 else if (answerList.get(i).fenzi == answerList.get(i).fenmu) {//分子等于分母,answer=1
232 arrayList.add(1+"");
233 }
234 else if (answerList.get(i).fenzi%answerList.get(i).fenmu == 0) {//分子能整除分母
235 arrayList.add(answerList.get(i).fenzi/answerList.get(i).fenmu + "");
236 }
237 else if((answerList.get(i).fenmu!=0)&&answerList.get(i).fenzi/answerList.get(i).fenmu> 1) {//假分数,转带分数
238 arrayList.add(answerList.get(i).fenzi/answerList.get(i).fenmu + "'"
239 + answerList.get(i).fenzi%answerList.get(i).fenmu + "/" + answerList.get(i).fenmu);
240 }
241 else {
242 arrayList.add(answerList.get(i).fenzi + "/" + answerList.get(i).fenmu + "");
243 }
244 }
245 return arrayList;
246 }
247
248
249
250
251 }
1 package Calculation;
2
3 import java.util.ArrayList;
4 import java.util.Stack;
5
6 /**
7 * 构造方法:生成查重表达式
8 * @author LHY
9 *
10 */
11 public class Repeat {
12 /**
13 * @param profixStack 后缀表达式栈
14 */
15 public Stack<Calcul_Expression> checkRepeat(Stack<Calcul_Expression> profixStack) {
16 // TODO Auto-generated constructor stub
17 Stack<Calcul_Expression> numberStack = new Stack<>(); //构造一个中间栈,存放数字
18 Stack<Calcul_Expression> checkStack = new Stack<>(); //存放查重表达式栈
19
20 // System.out.println(1);
21 Calcul_Expression bookNode = new Calcul_Expression(true, 0,0);
22 // System.out.println(2);
23 Calcul_Expression node1 = new Calcul_Expression();
24 Calcul_Expression node2 = new Calcul_Expression();
25 while(!profixStack.isEmpty()){//扫描后缀表达式栈直至其为空
26 Calcul_Expression proStack_top = profixStack.pop();//开始扫描第一个
27 if (!proStack_top.isysf&&!(proStack_top.fenzi==0&&proStack_top.fenmu==0)) {//若后缀表达式栈顶元素为数字。若非#则进numberStack
28 numberStack.push(proStack_top);
29 // System.out.println(proStack_top);
30 }
31 // else if (proStack_top.isOperator&&proStack_top.numerator==0&&proStack_top.denominator==0) {
32 // numberStack.pop();
33 // }
34 else if (proStack_top.isysf) {//后缀表达式栈顶为运算符,则进checkStack,再pop两个数字,并把#压进数字
35 checkStack.push(proStack_top);
36 if (numberStack.size() > 1) {
37 if (!(node1=numberStack.pop()).isysf&&!(node1.fenzi==0)&&!(node1.fenmu==0)) {//非#
38 checkStack.push(node1);
39 }
40 if (!(node2=numberStack.pop()).isysf&&!(node2.fenzi==0)&&!(node2.fenmu==0)) {
41 checkStack.push(node2);
42 }
43 }
44 numberStack.push(bookNode);
45 }
46
47 }//end while
48 System.out.println("size"+checkStack.size());
49 for(Calcul_Expression node:checkStack){
50 if (node.isysf) {
51 System.out.print(node.ysf + " ");
52 }else if(!node.isysf){
53 System.out.print(node.fenzi + "/" + node.fenmu + " ");
54 }
55 }
56 return checkStack;
57
58 }
59
60 public boolean IsRepeat(Stack<Calcul_Expression> exp1,Stack<Calcul_Expression> exp2){
61 Repeat repeat=new Repeat();
62 //转成查重表达式
63 ArrayList<Calcul_Expression> temp=new ArrayList<Calcul_Expression>();//中间存放栈1
64 Calcul_Expression tempNode=new Calcul_Expression();//中间交换结点
65 Stack<Calcul_Expression> checkRepeat1=repeat.checkRepeat(exp1);
66 Stack<Calcul_Expression> checkRepeat2=repeat.checkRepeat(exp2);
67 Stack<Calcul_Expression> newStack=new Stack<Calcul_Expression>();//交换后的新栈
68 int lengthRe1=checkRepeat1.size();
69 int lengthRe2=checkRepeat2.size();
70 System.out.println(1);
71 if(lengthRe1!=lengthRe2) return false;//若长度不相等,则表达式一定不同
72 System.out.println(2);
73 for(Calcul_Expression n:checkRepeat1){
74 temp.add(n);
75 }
76 if (this.isEqual(checkRepeat1, checkRepeat2)) {//完全一样则返回true
77 return true;
78 }
79
80 if(temp.get(0).ysf.equals("+")||temp.get(0).ysf.equals("*")){//只有加或乘的情况才可能出现 交换左右操作数当做重复的表达式
81 tempNode=temp.get(1);
82 temp.set(1, temp.get(2));
83 temp.set(2, tempNode);
84 }
85 for(Calcul_Expression p:temp){
86 newStack.push(p);
87 }
88 if(this.isEqual(newStack, checkRepeat2)) return true;//若交换后也相等则重复
89 System.out.println(3);
90 return false;
91 }
92
93 public boolean isEqual(Stack<Calcul_Expression> stack1,Stack<Calcul_Expression> stack2) {
94 Stack<Calcul_Expression> s1 = new Stack<>();
95 Stack<Calcul_Expression> s2 = new Stack<>();
96
97 Calcul_Expression s1_top;
98 Calcul_Expression s2_top;
99 for(Calcul_Expression node1:stack1){
100 s1.push(node1);
101 }
102 for(Calcul_Expression node2:stack2){
103 s2.push(node2);
104 }
105
106 while (!s1.isEmpty()&&!s2.isEmpty()) {
107 s1_top = s1.pop();
108 s2_top = s2.pop();
109 if (s1_top.isysf) {//若s1栈顶为运算符
110 if (s2_top.isysf&&(!s2_top.ysf.equals(s1_top.ysf))) {//s2都为运算符但s1不等于s2
111 return false;
112 }
113 else if (!s2_top.isysf) {//s1为运算符,s2非运算符
114 return false;
115 }
116 }
117 else if (!s1_top.isysf) {//若s1操作数
118 if (s2_top.isysf) {//s2为运算符
119 return false;
120 }
121 else if (!s2_top.isysf&&(s2_top.compareFraction(s1_top, s2_top)!=1)) {//s2为操作数但不等于s1
122 return false;
123 }
124 }
125
126 }
127 return true;
128 }
129 }
int count=0;
ArrayList<String> finalExp=new ArrayList<>();//最终所有表达式
ArrayList<Calcul_Expression> finalRes=new ArrayList<>();//最终所有结果(假分数)
ArrayList<String> realRes =new ArrayList<>();//最终所有结果(真分数)
ArrayList<Stack<Calcul_Expression>> checkArray=new ArrayList<>();//查重存放数组
Repeat repeat=new Repeat();
do {
boolean flag=false;
Stack<String> ac=new Stack<String>();
ac=After_Expression.toAfter_Expression(Ran_Expression.creatAc(range));//没带分母的后缀表达式
CaoZuoShu_handle handle=new CaoZuoShu_handle(ac);//带分母的后缀表达式
Calcul_Expression node=new Calcul_Expression();
Stack<Calcul_Expression> stack=new Stack<Calcul_Expression>();
stack=node.calculate(handle.posfixStack);//计算结果
if(stack.peek().ysf!="#"&&count==0){//非负,第一个表达式
checkArray.add(handle.posfixStack);
finalExp.add(Ran_Expression.exp_str);
finalRes.add(stack.peek());
count++;
}
if(stack.peek().ysf!="#"&&count>0){//非负,第二个表达式开始
for(Stack<Calcul_Expression> p:checkArray){
if(repeat.isEqual(p, handle.posfixStack)){
flag=true;
}
}
if(!flag){
checkArray.add(handle.posfixStack);
finalExp.add(Ran_Expression.exp_str);
finalRes.add(stack.peek());
count++;
}
}
} while (count!=number);
Calcul_Expression transNode=new Calcul_Expression();
realRes=transNode.imTomix(finalRes);
for (int i = 0; i < finalExp.size(); i++) {
System.out.println("第"+i+"题:"+finalExp.get(i));
}
for (int i = 0; i < realRes.size(); i++) {
System.out.println("第"+i+"题答案:"+realRes.get(i));
}
System.out.println("答案真正长度"+finalRes.size());
package Calculation;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import javax.imageio.spi.RegisterableService;
public class FileRW {
/**
* 将题目和答案写出在txt文件中
* @param expList 题目集合
* @param answerList 答案集合
* @return true 成功
* false 失败
*/
public boolean fileWrite(ArrayList<String> expList,ArrayList<Calcul_Expression> answerList) {
ArrayList<String> outList = new ArrayList<>();
if (expList.size()!=answerList.size()) {
System.out.println("答案与题目数目不匹配!");
return false;
}
for (int i = 0; i < expList.size(); i++) {
System.out.println();
outList.add(expList.get(i) + " = " +answerList.get(i).fenzi + "/"+ answerList.get(i).fenmu);
}
//开始写入文件
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
for(String s:outList){
bw.write(s);
bw.newLine();
bw.flush();
}
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
/**
* 把题目写出到文件
* @param expList
* @return
*/
public File writeQ(ArrayList<String> expList) {
int count = 1;
File file = new File("Question.txt");
try {
FileWriter fWriter = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fWriter);
for(String s:expList){
bw.write( count++ + "." +s);
bw.newLine();
bw.flush();
}
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return file;
}
/**
* 把答案写出到文件
* @param answerList
* @return
* @throws IOException
*/
public File writeA(ArrayList<String> answerList) throws IOException {
int count = 1;
File file = new File("Answer.txt");
FileWriter fWriter = new FileWriter(file);
try {
BufferedWriter bw = new BufferedWriter(fWriter);
for(String s:answerList){
bw.write( count++ + "." +s);
bw.newLine();
bw.flush();
}
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return file;
}
/**
*
* @param answerFile 待检测文件
* @param answerList 正确答案文件
* @return
*/
public File checkAnswer(File answerFile,File answerList) {
try {
BufferedReader rightReader = new BufferedReader(new FileReader(answerList));
BufferedReader anserReader = new BufferedReader(new FileReader(answerFile));
String rightString = null;
String answerString = null;
int right = 0;
int wrong = 0;
int line = 1;
String Rnumber="";
String Wnumber="";
//比较对错
while((rightString=rightReader.readLine())!=null&&(answerString=anserReader.readLine())!=null){
if(rightString.equals(answerString)){
right ++;
if (Rnumber.equals("")) {
Rnumber = Rnumber +line;
}
else{
Rnumber = Rnumber + ","+line;
}
}
else {
System.out.println(rightString);
System.out.println(answerString);
wrong++;
if (Wnumber.equals("")) {
Wnumber = Wnumber +line;
}else{
Wnumber = Wnumber + "," +line;
}
}
line++;
}
//写入到answerfile中
BufferedWriter bw = new BufferedWriter(new FileWriter(answerFile, true));
bw.newLine();
bw.write("right: "+ right + " " + "("+ Rnumber +")" + ";");
bw.newLine();
bw.write("wrong: "+ wrong + " " + "("+ Wnumber + ")"+ ";");
bw.flush();
bw.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return answerFile;
}
}




代码覆盖率:

|
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
|
Planning |
计划 |
45 |
47 |
|
· Estimate |
· 估计这个任务需要多少时间 |
45 |
47 |
|
Development |
开发 |
1405 |
1492 |
|
· Analysis |
· 需求分析 (包括学习新技术) |
80 |
95 |
|
· Design Spec |
· 生成设计文档 |
40 |
36 |
|
· Design Review |
· 设计复审 (和同事审核设计文档) |
45 |
55 |
|
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
35 |
30 |
|
· Design |
· 具体设计 |
120 |
107 |
|
· Coding |
· 具体编码 |
960 |
1050 |
|
· Code Review |
· 代码复审 |
50 |
35 |
|
· Test |
· 测试(自我测试,修改代码,提交修改) |
75 |
84 |
|
Reporting |
报告 |
180 |
235 |
|
· Test Report |
· 测试报告 |
120 |
180 |
|
· Size Measurement |
· 计算工作量 |
20 |
20 |
|
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
40 |
35 |
|
合计 |
|
1630 |
1774 |
这次结对编程项目相比上次的个人项目,整体的完成过程要更为复杂一些,也更加耗时间。做个人项目的时候,可以自己按照自己整体的代码构架和实现思路去走,在类的创建和实现上,也比较自由。而本次结对编程,就要求我们在团队协作这一块上一定要做得好,两个人一起实现同一个项目并不是一件简单的事情。我们在一开始对项目设计的讨论中,由于没有很明确地达成一致的思路,可以说只是商定了一个大概的框架,所以真正在分工实现项目的过程中,难免出现了一些问题,在最后联结双方的项目工程时发现无法完全契合双方的各种实现类。于是,在经过第二轮的讨论交流和实践修改后,才得以完成本次结对编程项目,这让我们都意识到小组交流和相互更新进度这些合作事宜的重要性。这次项目也让我们两个人从中学到了很多,明确了彼此的一些知识盲区,相信有了结对编程的经验后,在后续的团队编程项目中我们会做得更好。