结对编程之四则运算(马仪生、李瑞恒)
github项目传送门:https://github.com/bpgg/FourArithmeticOperation
项目要求
- 功能列表
- [完成] 使用 -n 参数控制生成题目的个数
- [完成] 使用 -r 参数控制题目中数值的范围, 。该参数可以设置为1或其他自然数。
- [完成] 生成的题目中计算过程不能产生负数
- [完成] 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。
- [完成] 程序一次运行生成的题目不能重复,生成的题目存入执行程序的当前目录下的Exercises.txt文件
- [完成] 每道题目中出现的运算符个数不超过3个
- [完成] 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件
- [完成] 程序应能支持一万道题目的生成。
- [未完成] 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计
PSP开发耗时
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
30 | 60 |
· Estimate |
· 估计这个任务需要多少时间 |
30 | 60 |
Development |
开发 |
1000 | 2240 |
· Analysis |
· 需求分析 (包括学习新技术) |
100 | 180 |
· Design Spec |
· 生成设计文档 |
60 | 100 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
30 | 30 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
30 | 30 |
· Design |
· 具体设计 |
120 | 150 |
· Coding |
· 具体编码 |
600 | 1500 |
· Code Review |
· 代码复审 |
50 | 60 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
150 | 60 |
Reporting |
报告 |
80 | 80 |
· Test Report |
· 测试报告 |
30 | 60 |
· Size Measurement |
· 计算工作量 |
20 | 10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 | 20 |
合计 |
1110 | 2400 |
· 思路分析
- 生成表达式
使用对象存储子表达式,两个子表达式组成一个总表达式
表达式对象使用字符串类型存储操作数和操作符
控制表达式符号与数字之间保留一个空格,方便后续筛选
- 检查是否重复
每生成一个表达式都会添加到列表里面
通过遍历列表的表达式确定是否为相同的表达式子,如果是,重新生成表达。
- 存储表达式存储
将生成的中缀表达式转化为后缀表达式
根据运算优先级将操作数和符号存储在对应节点中
父节点存储运算符号,子节点存储操作数
例如: 3+2+1
- 计算表达式结果
根据表达式对应的二叉树进行计算,
将左右子节点进行操作之后把值赋给父节点
重复上述操作,直到根节点停止
根节点的值即为所求
并将所求值存储在答案列表里
- 写入文件
遍历表达式列表和答案列表
分别写入对应的文件
程序流程图
用户使用说明
举例:
-n [数值] 使用 -n 参数控制生成题目的个数。
-r [数值] 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围。
代码
项目目录:
生成表达式:
- 生成操作数
public String generateOperand(int iRange){String sOpreand="";switch(randomer.nextInt(3)) {case 0://生成带分数sOpreand = (randomer.nextInt(iRange)+1)+"’"+generatePrimes(iRange);break;case 1:sOpreand = generatePrimes(iRange);break;case 2:sOpreand =String.valueOf(randomer.nextInt(iRange)+1);break;}return sOpreand;}
- 生成分数(分子分母互质,无需约分)
b private String generatePrimes(int iRange){//分子最大为8int iNumerator=randomer.nextInt(iRange)+1;int iDenominator=iNumerator+randomer.nextInt(iRange)+1;//保证两个数互质if(iNumerator==0){//分子为0,分母直接使用return iNumerator+"/"+iDenominator;}int comDivisor = getComDivisor(iNumerator, iDenominator);iNumerator/=comDivisor;iDenominator/=comDivisor;return iNumerator+"/"+iDenominator;}
- 数值互转及详细操作
1 package utils; 2 3 import exception.IllegalSituationException; 4 5 public class CalculateUtil { 6 7 //加法 8 9 /** 10 * 两个数的相加 11 * 12 * @param a 加数 13 * @param b 加数 14 * @return 结果 15 */ 16 public static String add(String a, String b) { 17 if (a.equals("0")||b.equals("0")){ 18 return a.equals("0")?b:a; 19 } 20 //两个都是自然数 21 if (isNaturalNumber(a) && isNaturalNumber(b)) { 22 return String.valueOf(Integer.valueOf(a) + Integer.valueOf(b)); 23 } 24 25 //两个都是分数 26 if (!isNaturalNumber(a) && !isNaturalNumber(b)) { 27 String m = getRealFraction(a); 28 String n = getRealFraction(b); 29 30 return simplify(addFractionAndFraction(m, n)); 31 32 } 33 //一个是自然数一个是分数 34 if (isNaturalNumber(a) && !isNaturalNumber(b)) { 35 String fraction = getRealFraction(b); 36 return simplify(addFractionAndNatural(a, fraction)); 37 } 38 39 //一个是分数一个是自然数 40 if (!isNaturalNumber(a) && isNaturalNumber(b)) { 41 String fraction = getRealFraction(a); 42 return simplify(addFractionAndNatural(b, fraction)); 43 } 44 45 return null; 46 47 } 48 49 /** 50 * 分数加自然数 ,int[0] 为分子, int[1] 为分母 51 * 52 * @param natural 自然数 53 * @param fraction 分数 54 * @return 结果 55 */ 56 private static String addFractionAndNatural(String natural, String fraction) { 57 int nat = Integer.valueOf(natural); 58 int[] numB = getDenominatorAndMolecule(fraction); 59 60 int molecule = nat * numB[1] + numB[0]; //分子 61 int denominator = numB[1]; // 分母 62 return molecule + "/" + denominator; 63 } 64 65 /** 66 * 两个分数相加 int[0] 为分子, int[1] 为分母 67 * 68 * @param a 加数 69 * @param b 加数 70 * @return 结果 71 */ 72 private static String addFractionAndFraction(String a, String b) { 73 int[] numA = getDenominatorAndMolecule(a); 74 int[] numB = getDenominatorAndMolecule(b); 75 76 int molecule = numA[0] * numB[1] + numB[0] * numA[1]; 77 int denominator = numA[1] * numB[1]; 78 79 return molecule + "/" + denominator; 80 81 } 82 83 //减法 84 85 /** 86 * 两个数的减法 87 * 88 * @param a 减数 89 * @param b 被减数 90 * @return 结果 91 */ 92 public static String subtract(String a, String b) { 93 if (a.equals("0")||b.equals("0")){ 94 return a.equals("0")? "-"+b:a; 95 } 96 //两个都是自然数 97 if (isNaturalNumber(a) && isNaturalNumber(b)) { 98 return String.valueOf(Integer.valueOf(a) - Integer.valueOf(b)); 99 } 100 101 //两个都是分数 102 if (!isNaturalNumber(a) && !isNaturalNumber(b)) { 103 String m = getRealFraction(a); 104 String n = getRealFraction(b); 105 106 return simplify(subtractFractionAndFraction(m, n)); 107 108 } 109 //一个是自然数一个是分数 110 if (isNaturalNumber(a) && !isNaturalNumber(b)) { 111 String fraction = getRealFraction(b); 112 return simplify(subtractFractionAndFraction(naturalToFraction(a, fraction), fraction)); 113 } 114 115 //一个是分数一个是自然数 116 if (!isNaturalNumber(a) && isNaturalNumber(b)) { 117 String fraction = getRealFraction(a); 118 return simplify(subtractFractionAndFraction(fraction, naturalToFraction(b, fraction))); 119 } 120 121 return null; 122 } 123 124 /** 125 * 自然数转分数 int[0] 为分子, int[1] 为分母 126 * 127 * @param natural 自然数 128 * @param fraction 分数 129 * @return 结果 130 */ 131 private static String naturalToFraction(String natural, String fraction) { 132 int[] numFrac = getDenominatorAndMolecule(fraction); 133 int molecule = Integer.valueOf(natural) * numFrac[1]; //分子 134 int denominator = numFrac[1]; // 分母 135 return molecule + "/" + denominator; 136 137 } 138 139 /** 140 * 分数减分数 int[0] 为分子, int[1] 为分母 141 * 142 * @param a 分数 143 * @param b 分数 144 * @return 结果 145 */ 146 private static String subtractFractionAndFraction(String a, String b) { 147 int[] numA = getDenominatorAndMolecule(a); 148 int[] numB = getDenominatorAndMolecule(b); 149 150 int molecule = numA[0] * numB[1] - numB[0] * numA[1]; //分子 151 int denominator = numA[1] * numB[1]; //分母 152 153 return molecule + "/" + denominator; 154 } 155 156 //乘法 157 158 /** 159 * 乘法 160 * 161 * @param a 乘数 162 * @param b 乘数 163 * @return 结果 164 */ 165 public static String multiplies(String a, String b) { 166 if (a.equals("0")||b.equals("0")){ 167 return String.valueOf(0); 168 } 169 //两个都是自然数 170 if (isNaturalNumber(a) && isNaturalNumber(b)) { 171 return String.valueOf(Integer.valueOf(a) * Integer.valueOf(b)); 172 } 173 174 //两个都是分数 175 if (!isNaturalNumber(a) && !isNaturalNumber(b)) { 176 String m = getRealFraction(a); 177 String n = getRealFraction(b); 178 179 return simplify(multipliesFractionAndFraction(m, n)); 180 181 } 182 //一个是自然数一个是分数 183 if (isNaturalNumber(a) && !isNaturalNumber(b)) { 184 String fraction = getRealFraction(b); 185 return simplify(multipliesFractionAndFraction(naturalToFraction(a, fraction), fraction)); 186 } 187 188 //一个是分数一个是自然数 189 if (!isNaturalNumber(a) && isNaturalNumber(b)) { 190 String fraction = getRealFraction(a); 191 return simplify((multipliesFractionAndFraction(fraction, naturalToFraction(b, fraction)))); 192 } 193 return null; 194 } 195 196 /** 197 * 分数乘分数 198 * 199 * @param a 分数 200 * @param b 分数 201 * @return 结果 202 */ 203 private static String multipliesFractionAndFraction(String a, String b) { 204 int[] numA = getDenominatorAndMolecule(a); 205 int[] numB = getDenominatorAndMolecule(b); 206 207 int molecule = numA[0] * numB[0]; //分子 208 int denominator = numA[1] * numB[1]; // 分母 209 210 return molecule + "/" + denominator; 211 } 212 213 /** 214 * 除法 215 * @param a 除数 216 * @param b 被除数 217 * @return 结果 218 */ 219 public static String divide(String a, String b) throws IllegalSituationException { 220 if (a.equals("0")){ 221 return String.valueOf(0); 222 } 223 if (b.equals("0")){ 224 throw new IllegalSituationException("Argument b can’t be zero"); 225 } 226 //两个都是自然数 227 if (isNaturalNumber(a) && isNaturalNumber(b)) { 228 return simplify(a + "/" + b); 229 } 230 231 //两个都是分数 232 if (!isNaturalNumber(a) && !isNaturalNumber(b)) { 233 String m = getRealFraction(a); 234 String n = getRealFraction(b); 235 return simplify(divideFractionAndFraction(m, n)); 236 237 } 238 //一个是自然数一个是分数 239 if (isNaturalNumber(a) && !isNaturalNumber(b)) { 240 String fraction = getRealFraction(b); 241 return simplify(divideFractionAndFraction(naturalToFraction(a, fraction), fraction)); 242 } 243 244 //一个是分数一个是自然数 245 if (!isNaturalNumber(a) && isNaturalNumber(b)) { 246 String fraction = getRealFraction(a); 247 return simplify(divideFractionAndFraction(fraction, naturalToFraction(b, fraction))); 248 } 249 250 return null; 251 } 252 253 /** 254 * 分数除分数 255 * @param a 除数 256 * @param b 被除数 257 * @return 结果 258 */ 259 private static String divideFractionAndFraction(String a, String b) { 260 int[] numA = getDenominatorAndMolecule(a); 261 int[] numB = getDenominatorAndMolecule(b); 262 263 int molecule = numA[0] * numB[1]; 264 int denominator = numA[1] * numB[0]; 265 266 return molecule + "/" + denominator; 267 } 268 269 270 /** 271 * 获取分数的分子和分母 272 * 273 * @param a 分数 274 * @return 结果,int[0] 为分子, int[1] 为分母 275 */ 276 private static int[] getDenominatorAndMolecule(String a) { 277 String numA[] = a.split("[/]"); 278 int numInt[] = new int[numA.length]; 279 for (int i = 0; i < numInt.length; i++) { 280 numInt[i] = Integer.valueOf(numA[i]); 281 282 } 283 return numInt; 284 } 285 286 /** 287 * 分数形式的转换 288 * 289 * @param s 分数 290 * @return 结果 291 */ 292 private static String getRealFraction(String s) { 293 if (isFalseFraction(s)) { //1"1/2 294 String numStr[] = s.split("[’/]"); 295 int numInt[] = new int[numStr.length]; 296 for (int i = 0; i < numInt.length; i++) { 297 numInt[i] = Integer.valueOf(numStr[i]); 298 299 } 300 int denominator = numInt[0] * numInt[2] + numInt[1]; 301 return denominator + "/" + numStr[2]; 302 } 303 304 return s; 305 } 306 307 /** 308 * 判断是否为自然数 309 * 310 * @param s 数 311 * @return 结果 312 */ 313 private static boolean isNaturalNumber(String s) { 314 return !s.contains("/"); 315 } 316 317 /** 318 * 判断是否为 假分数 319 * 320 * @param s 数 321 * @return 结果 322 */ 323 private static boolean isFalseFraction(String s) { 324 return s.contains("’"); 325 } 326 327 private static String simplify(String fraction){ 328 int[] num = getDenominatorAndMolecule(fraction); 329 int molecule = num[0] ; 330 int denominator = num[1] ; 331 if (molecule==0){ 332 return String.valueOf(0); 333 } 334 if (molecule==denominator){ 335 return "1"; 336 } 337 338 if (molecule<denominator){ 339 int i ; 340 if ((i=gcd(molecule,denominator))==1){ 341 return molecule +"/" +denominator; 342 } 343 molecule = molecule/i; 344 denominator = denominator/i; 345 return molecule +"/" +denominator; 346 } 347 348 if (molecule>denominator){ 349 int i = gcd(molecule,denominator); 350 molecule = molecule/i; 351 denominator = denominator/i; 352 353 if (denominator==1){ 354 return molecule+""; 355 356 } 357 358 return getWithFraction(molecule,denominator); 359 360 } 361 362 return null; 363 364 } 365 366 /** 367 * 获取带分数 368 * @param molecule 分子 369 * @param denominator 分母 370 * @return 结果 371 */ 372 private static String getWithFraction(int molecule,int denominator){ 373 int withFraction = (molecule - (molecule%denominator)) / denominator; 374 molecule = molecule%denominator; 375 return withFraction+"’"+molecule+"/"+denominator; 376 } 377 378 /** 379 * 求最大公约数,欧几里得方法 380 * @param m 数1 381 * @param n 数 382 * @return 结果 383 */ 384 private static int gcd(int m, int n) { 385 return n == 0 ? m : gcd(n, m % n); 386 } 387 388 public static boolean isNegative(String num){ 389 return num.contains("-"); 390 } 391 }
- 后缀表达式处理数据
public static String InfixToPostfix(String expression) {String str[] = expression.split("\\s+");for (String s : str) {//四个操作符if (isOperator(s)) {handleOperator(s);continue;}//左括号,入栈if (s.equals("(")) {mStack.push(s);continue;}//右括号,弹出并输出,直到遇到左括号,左括号也弹出if (s.equals(")")) {while (!mStack.peek().equals("(")) {mExp.append(mStack.pop());mExp.append(" ");}mStack.pop();continue;}mExp.append(s);mExp.append(" ");}//栈中还有数据,直接出栈输出while (!mStack.empty()) {mExp.append(mStack.pop());mExp.append(" ");}return mExp.toString();}
- 输出表达式到Exercises.txt和输出答案到Answers.txt:
private static void doWork(int iQuestions,int iRange){while (mList.size() != iQuestions) {String ex = Operation.generateQuestion();Node tree = TreeUtil.createTree(StringUtil.InfixToPostfix(ex));if (generate1(tree).isIllegal() && !isEquals(mResult)) {mResult.setExpression(ex);mList.add(mResult);}}//文件操作对象 FileOutputStream outSTr1 ;FileOutputStream outSTr2 ;BufferedOutputStream Buff1;BufferedOutputStream Buff2;long begin0 = System.currentTimeMillis();try {outSTr1 = new FileOutputStream(new File(".\\Exercises.txt"));outSTr2 = new FileOutputStream(new File(".\\Answers.txt"));Buff1 = new BufferedOutputStream(outSTr1);Buff2 = new BufferedOutputStream(outSTr2);for(int i=0; i<mList.size();i++){Buff1.write(((i+1)+" 、"+mList.get(i).getExpression()+"\r\n").getBytes());Buff2.write(((i+1)+" 、"+mList.get(i).getResult()+"\r\n").getBytes());}Buff1.flush();Buff2.flush();Buff1.close();Buff2.close();long end0 = System.currentTimeMillis();System.out.println("BufferedOutputStream执行耗时:" + (end0 - begin0) + " 毫秒");} catch(Exception e){System.out.println("出现异常:" + e.getMessage());}}
测试运行
表达式的输出
-n 10 -e 10
9’9/10 + 6’6/11 × 9 - 6 = 62’89/110
5 × 3’1/7 = 15’5/7
3’1/9 - 1/2 = 2’11/18
9 + 10/17 + 2 × 9 = 27’10/17
9 + 2’3/13 ÷ 1/4 = 17’12/13
3’5/7 + 8 - 2 = 9’5/7
6’2/5 ÷ 9’3/4 ÷ 10’1/2 = 256/4095
4’1/5 + 6/11 ÷ 9 = 4’43/165
9’7/16 ÷ 3/7 - 5 = 17’1/48
2’6/13 × 2’5/14 = 5’73/91
- 随机输出10000条10范围以内的表达式和答案:
10000个答案
https://github.com/bpgg/FourArithmeticOperation/blob/master/src/Answers.txt
10000个表达式
https://github.com/bpgg/FourArithmeticOperation/blob/master/src/Exercises.txt
总结
在与马仪生的合作中,我体验到了直接调用别人写好的接口的快乐。在本次实验中,我主要负责生成表达式及总结,仪生主要负责处理表达式。在与仪生的合作中,我了解到更多编码规范,必须对象类的报名定义为bean,一些固定的常量也需要放在const包中,调用的工具类放在util包里,把各种功能实现分开实现,最后集中使用,便于维护的同时也是代码更加清晰。
转载于:https://www.cnblogs.com/fyy30/p/9710972.html
结对编程之四则运算(马仪生、李瑞恒)相关推荐
- 20165330 结对编程项目-四则运算 第一周
需求分析 实现一个命令行程序,要求:自动生成小学四则运算题目(加.减.乘.除) 可实现多个运算符一起运算 可以真分数形式输出结果 测试结果的正确性 统计题目完成数并计算正确率 设计思路 实验首先是完成 ...
- 20172307 结对编程项目-四则运算 第二周 阶段总结
20172307 结对编程项目-四则运算 第二周 阶段总结 (结队项目码云地址) 相关过程截图(关键代码处加了注释) 编写出实现中缀转后缀的类Transform /*Transform.java 作者 ...
- 20165318 结对编程项目-四则运算 阶段总结
20165318 结对编程项目-四则运算 阶段总结 目录 一.需求分析 二.设计思路 三.实现过程中的关键代码解释 四.测试方法 五.运行过程截图 六.代码托管 七.遇到的困难及解决方法 八.对结对小 ...
- 结对编程项目-四则运算阶段性总结
结对编程项目-四则运算阶段性总结 在这段时间的结对编程过程中,我和我的组员一同编程,初步完成了项目的要求,现在我将阶段性的成果做一个总结 一.需求分析 实现一个命令行程序,要求: 1.自动生成小学四则 ...
- 结对编程项目-四则运算整体总结
结对编程项目-四则运算整体总结 在这一周中,我和我的搭档完成项目并实现了拓展需求,现在我将本项目的成果做一个总结 一.需求分析 实现一个命令行程序,要求: 1.自动生成小学四则运算题目(加.减.乘.除 ...
- java安装 1723_2017-2018-2 1723 『Java程序设计』课程 结对编程练习-四则运算-准备阶段...
2017-2018-2 1723 『Java程序设计』课程 结对编程练习-四则运算-准备阶段 在一个人孤身奋斗了将近半个学期以后,终于迎来的我们的第一次团队协作共同编码,也就是,我们的第一个结对编程练 ...
- 结对编程项目-四则运算(第一周阶段性总结)
结对编程项目-四则运算(阶段性总结) 需求分析 题目生成 多运算符(可设计层级) 包含括号(可单独使用) 无重复题目(可单独使用) 生成有意义的题目(例如:5x(5x5)等等) 等级划分 Level ...
- 结对编程作业——四则运算
Github项目地址 PSP PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 10 10 · Estimat ...
- 结对编程1 - 四则运算生成器的改进(201421123040,60,61)
题目要求 我们在个人作业1中,用各种语言实现了一个命令行的四则运算小程序.进一步,本次要求把这个程序做成GUI(可以是Windows PC 上的,也可以是Mac.Linux,web,手机上的),成为一 ...
最新文章
- Apache Kafka-初体验Kafka(04)-Java客户端操作Kafka
- 开发备必:WEB前端开发规范文档
- Java实现doc或xls转PDF
- Jdbc连接mysql的五种连接方式
- 笔记本计算机死机后如何启动,电脑戴尔死机如何重新启动的解决方法
- android-HttpClient上传信息(包括图片)到服务端
- 剑桥offer(41~50)
- 【TensorFlow-windows】(五) CNN(卷积神经网络)对cifar10的识别
- 下载软件的临时文件思路和实现
- 浅析计算机科学在经济犯罪中的特征与表现
- 利用MATLAB编程或者Simulink工具来绘制伯德图和奈奎斯特图
- 论文查找(网络与信息安全)
- 聊聊Netflix的技术创新
- 51单片机对直流电机的控制(使用proteus仿真)
- 装出一个好的WIN2000最经典的步骤
- python os库的常用函数记录
- redis简略版笔记
- Driver中使用的内核机制
- solidity 中的时间_solidity基础知识
- CANopen通信之NMT通信