结对编程之四则运算(马仪生、李瑞恒)
github項目傳送門:https://github.com/bpgg/FourArithmeticOperation
項目要求
-?功能列表
?
PSP開發(fā)耗時
| PSP2.1 | Personal Software Process Stages | 預(yù)估耗時(分鐘) | 實際耗時(分鐘) |
| Planning | 計劃 | ?30 | ?60 |
| · Estimate | · 估計這個任務(wù)需要多少時間 | ?30 | ?60 |
| Development | 開發(fā) | ?1000 | ?2240 |
| · Analysis | · 需求分析 (包括學(xué)習(xí)新技術(shù)) | ?100 | ?180 |
| · Design Spec | · 生成設(shè)計文檔 | ?60 | ?100 |
| · Design Review | · 設(shè)計復(fù)審 (和同事審核設(shè)計文檔) | ?30 | ?30 |
| · Coding Standard | · 代碼規(guī)范 (為目前的開發(fā)制定合適的規(guī)范) | ?30 | ?30 |
| · Design | · 具體設(shè)計 | ?120 | ?150 |
| · Coding | · 具體編碼 | ?600 | ?1500 |
| · Code Review | · 代碼復(fù)審 | ?50 | ?60 |
| · Test | · 測試(自我測試,修改代碼,提交修改) | ?150 | ?60 |
| Reporting | 報告 | ?80 | ?80 |
| · Test Report | · 測試報告 | ?30 | ?60 |
| · Size Measurement | · 計算工作量 | ?20 | ?10 |
| · Postmortem & Process Improvement Plan | · 事后總結(jié), 并提出過程改進計劃 | ?30 | ?20 |
| 合計 | ? | ?1110 | ?2400 |
?
· 思路分析
- 生成表達式
使用對象存儲子表達式,兩個子表達式組成一個總表達式
表達式對象使用字符串類型存儲操作數(shù)和操作符
控制表達式符號與數(shù)字之間保留一個空格,方便后續(xù)篩選
- 檢查是否重復(fù)
每生成一個表達式都會添加到列表里面
通過遍歷列表的表達式確定是否為相同的表達式子,如果是,重新生成表達。
- 存儲表達式存儲
將生成的中綴表達式轉(zhuǎn)化為后綴表達式
根據(jù)運算優(yōu)先級將操作數(shù)和符號存儲在對應(yīng)節(jié)點中
父節(jié)點存儲運算符號,子節(jié)點存儲操作數(shù)
例如: 3+2+1
?
- 計算表達式結(jié)果
根據(jù)表達式對應(yīng)的二叉樹進行計算,
將左右子節(jié)點進行操作之后把值賦給父節(jié)點
重復(fù)上述操作,直到根節(jié)點停止
根節(jié)點的值即為所求
并將所求值存儲在答案列表里
- 寫入文件
遍歷表達式列表和答案列表
分別寫入對應(yīng)的文件
?
程序流程圖
?
?
?
?
?
用戶使用說明
舉例:
-n? ?[數(shù)值] ? ? 使用 -n 參數(shù)控制生成題目的個數(shù)。
-r? ?[數(shù)值] ? ? 使用 -r 參數(shù)控制題目中數(shù)值(自然數(shù)、真分數(shù)和真分數(shù)分母)的范圍。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
?
代碼
項目目錄:
?
?生成表達式:
- 生成操作數(shù)
public String generateOperand(int iRange){String sOpreand="";switch(randomer.nextInt(3)) {case 0://生成帶分數(shù)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;}?
?- 生成分數(shù)(分子分母互質(zhì),無需約分)
b private String generatePrimes(int iRange){//分子最大為8int iNumerator=randomer.nextInt(iRange)+1;int iDenominator=iNumerator+randomer.nextInt(iRange)+1;//保證兩個數(shù)互質(zhì)if(iNumerator==0){//分子為0,分母直接使用return iNumerator+"/"+iDenominator;}int comDivisor = getComDivisor(iNumerator, iDenominator);iNumerator/=comDivisor;iDenominator/=comDivisor;return iNumerator+"/"+iDenominator;}?
?
?- 數(shù)值互轉(zhuǎn)及詳細操作
1 package utils; 2 3 import exception.IllegalSituationException; 4 5 public class CalculateUtil { 6 7 //加法 8 9 /** 10 * 兩個數(shù)的相加 11 * 12 * @param a 加數(shù) 13 * @param b 加數(shù) 14 * @return 結(jié)果 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 //兩個都是自然數(shù) 21 if (isNaturalNumber(a) && isNaturalNumber(b)) { 22 return String.valueOf(Integer.valueOf(a) + Integer.valueOf(b)); 23 } 24 25 //兩個都是分數(shù) 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 //一個是自然數(shù)一個是分數(shù) 34 if (isNaturalNumber(a) && !isNaturalNumber(b)) { 35 String fraction = getRealFraction(b); 36 return simplify(addFractionAndNatural(a, fraction)); 37 } 38 39 //一個是分數(shù)一個是自然數(shù) 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 * 分數(shù)加自然數(shù) ,int[0] 為分子, int[1] 為分母 51 * 52 * @param natural 自然數(shù) 53 * @param fraction 分數(shù) 54 * @return 結(jié)果 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 * 兩個分數(shù)相加 int[0] 為分子, int[1] 為分母 67 * 68 * @param a 加數(shù) 69 * @param b 加數(shù) 70 * @return 結(jié)果 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 * 兩個數(shù)的減法 87 * 88 * @param a 減數(shù) 89 * @param b 被減數(shù) 90 * @return 結(jié)果 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 //兩個都是自然數(shù) 97 if (isNaturalNumber(a) && isNaturalNumber(b)) { 98 return String.valueOf(Integer.valueOf(a) - Integer.valueOf(b)); 99 } 100 101 //兩個都是分數(shù) 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 //一個是自然數(shù)一個是分數(shù) 110 if (isNaturalNumber(a) && !isNaturalNumber(b)) { 111 String fraction = getRealFraction(b); 112 return simplify(subtractFractionAndFraction(naturalToFraction(a, fraction), fraction)); 113 } 114 115 //一個是分數(shù)一個是自然數(shù) 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 * 自然數(shù)轉(zhuǎn)分數(shù) int[0] 為分子, int[1] 為分母 126 * 127 * @param natural 自然數(shù) 128 * @param fraction 分數(shù) 129 * @return 結(jié)果 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 * 分數(shù)減分數(shù) int[0] 為分子, int[1] 為分母 141 * 142 * @param a 分數(shù) 143 * @param b 分數(shù) 144 * @return 結(jié)果 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 乘數(shù) 162 * @param b 乘數(shù) 163 * @return 結(jié)果 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 //兩個都是自然數(shù) 170 if (isNaturalNumber(a) && isNaturalNumber(b)) { 171 return String.valueOf(Integer.valueOf(a) * Integer.valueOf(b)); 172 } 173 174 //兩個都是分數(shù) 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 //一個是自然數(shù)一個是分數(shù) 183 if (isNaturalNumber(a) && !isNaturalNumber(b)) { 184 String fraction = getRealFraction(b); 185 return simplify(multipliesFractionAndFraction(naturalToFraction(a, fraction), fraction)); 186 } 187 188 //一個是分數(shù)一個是自然數(shù) 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 * 分數(shù)乘分數(shù) 198 * 199 * @param a 分數(shù) 200 * @param b 分數(shù) 201 * @return 結(jié)果 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 除數(shù) 216 * @param b 被除數(shù) 217 * @return 結(jié)果 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 //兩個都是自然數(shù) 227 if (isNaturalNumber(a) && isNaturalNumber(b)) { 228 return simplify(a + "/" + b); 229 } 230 231 //兩個都是分數(shù) 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 //一個是自然數(shù)一個是分數(shù) 239 if (isNaturalNumber(a) && !isNaturalNumber(b)) { 240 String fraction = getRealFraction(b); 241 return simplify(divideFractionAndFraction(naturalToFraction(a, fraction), fraction)); 242 } 243 244 //一個是分數(shù)一個是自然數(shù) 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 * 分數(shù)除分數(shù) 255 * @param a 除數(shù) 256 * @param b 被除數(shù) 257 * @return 結(jié)果 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 * 獲取分數(shù)的分子和分母 272 * 273 * @param a 分數(shù) 274 * @return 結(jié)果,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 * 分數(shù)形式的轉(zhuǎn)換 288 * 289 * @param s 分數(shù) 290 * @return 結(jié)果 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 * 判斷是否為自然數(shù) 309 * 310 * @param s 數(shù) 311 * @return 結(jié)果 312 */ 313 private static boolean isNaturalNumber(String s) { 314 return !s.contains("/"); 315 } 316 317 /** 318 * 判斷是否為 假分數(shù) 319 * 320 * @param s 數(shù) 321 * @return 結(jié)果 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 * 獲取帶分數(shù) 368 * @param molecule 分子 369 * @param denominator 分母 370 * @return 結(jié)果 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 * 求最大公約數(shù),歐幾里得方法 380 * @param m 數(shù)1 381 * @param n 數(shù) 382 * @return 結(jié)果 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 }?
?
- 后綴表達式處理數(shù)據(jù)
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(" ");}//棧中還有數(shù)據(jù),直接出棧輸出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執(zhí)行耗時:" + (end0 - begin0) + " 毫秒");} catch(Exception e){System.out.println("出現(xiàn)異常:" + 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范圍以內(nèi)的表達式和答案:
10000個答案?
https://github.com/bpgg/FourArithmeticOperation/blob/master/src/Answers.txt
10000個表達式
https://github.com/bpgg/FourArithmeticOperation/blob/master/src/Exercises.txt
總結(jié)
在與馬儀生的合作中,我體驗到了直接調(diào)用別人寫好的接口的快樂。在本次實驗中,我主要負責(zé)生成表達式及總結(jié),儀生主要負責(zé)處理表達式。在與儀生的合作中,我了解到更多編碼規(guī)范,必須對象類的報名定義為bean,一些固定的常量也需要放在const包中,調(diào)用的工具類放在util包里,把各種功能實現(xiàn)分開實現(xiàn),最后集中使用,便于維護的同時也是代碼更加清晰。
?
轉(zhuǎn)載于:https://www.cnblogs.com/fyy30/p/9710972.html
總結(jié)
以上是生活随笔為你收集整理的结对编程之四则运算(马仪生、李瑞恒)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 密钥对加密原理
- 下一篇: 深入理解Java:注解(Annotati