这个作业属于哪个课程 | 班级链接 |
---|---|
这个作业要求在哪里 | 作业链接 |
这个作业的目标 | 四则运算生成器+生成应用程序+结对 |
项目成员1 | 3119005418蓝泽凯(GitHub地址) |
项目成员2 | 3119005425刘原维(GitHub地址) |
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 90 | 120 |
· Estimate | · 估计这个任务需要多少时间 | 90 | 120 |
Development | 开发 | 1320 | 1540 |
· Analysis | · 需求分析 (包括学习新技术) | 80 | 90 |
· Design Spec | · 生成设计文档 | 40 | 40 |
· Design Review | · 设计复审 | 30 | 30 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
· Design | · 具体设计 | 90 | 120 |
· Coding | · 具体编码 | 800 | 920 |
· Code Review | · 代码复审 | 30 | 30 |
· Test | · 测试(自我测试,修改代码,提交修改) | 240 | 300 |
Reporting | 报告 | 60 | 70 |
· Test Report | · 测试报告 | 30 | 40 |
· Size Measurement | · 计算工作量 | 10 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
· 合计 | 1470 | 1730 |
//获取完整表达式,合法的数字、符号、括号顺序 public static List<String> getExpression() { int numCount = random.nextInt(maxNumCount - 1) + 2; int opCount = numCount - 1; Stack<String> numStack = new Stack<>(); Stack<Character> opStack = new Stack<>(); Stack<String> numStack1 = (Stack<String>) numStack.clone(); Stack<Character> opStack1 = (Stack<Character>) opStack.clone(); //接收随机数和随机运算符; String[] nums = MathUtils.getNum(numCount); char[] operations = MathUtils.getOperation(opCount); //分别将数字和符号入栈 for (String num : nums) { numStack.push(num); } for (Character op : operations) { opStack.push(op); } List<String> expressionList = new ArrayList<>(); int leftC = 0; int leftNum = 0; while (!opStack.empty()) { expressionList.add(numStack.pop()); leftNum++; if ((int) (Math.random() * 10) % 3 == 0 && leftC > 0 && leftNum > 1) { expressionList.add(")"); leftC--; expressionList.add(String.valueOf(opStack.pop())); leftNum = 0; break; } expressionList.add(String.valueOf(opStack.pop())); if ((int) (Math.random() * 10) % 4 == 0 && numStack.size() > 2) { expressionList.add("("); leftC++; leftNum = 0; } } expressionList.add(numStack.pop()); if (leftC > 0) { for (int j = 0; j < leftC; j++) { expressionList.add(")"); } } expressionList.add("="); return expressionList; }
public static Stack<String> calculate(String expression) throws ZeroDivException, NegativeNumberException { String newException = expression.replace("=",""); String[] parts = newException.split(" "); Stack<String> numStack= new Stack<>(); Stack<String> opStack =new Stack<>(); Stack<String> progressStack =new Stack<>();//过程栈 for (String part : parts) { if (ExpressionUtils.isNum(part)){numStack.push(part);continue;}//如果是数字,直接入栈; if (ExpressionUtils.isOp(part)){ if (")".equals(part)){ while (!"(".equals(opStack.peek())){ String op = opStack.pop();//弹出运算符 String b = numStack.pop();//先弹出的是b String a = numStack.pop();//后弹出的是a String result = calculate(a,b,op); numStack.push(result); progressStack.push(result);//中间结果入栈 } opStack.pop(); continue; }//如果当前符号是右括号),一直弹栈直到遇到第一个左括号,把左括号弹出并结束循环 if (opStack.empty()){opStack.push(part);continue;}//如果运算符栈为空直接入栈 if ("(".equals(part)){opStack.push(part);continue;} if (ExpressionUtils.priority(part)>ExpressionUtils.priority(opStack.peek())){//如果运算符栈不为空,判断优先级 opStack.push(part);//如果优先级高于当前栈顶 }else {//如果优先级不高于栈顶 while (!opStack.empty()){ if (ExpressionUtils.priority(opStack.peek())<ExpressionUtils.priority(part)){break;}//直到运算符栈顶运算符优先级低于当前的,或者 if ("(".equals(opStack.peek())){break;}//如果栈顶是左括号,将运算符入栈并跳出循环 String op = opStack.pop();//弹出运算符 String b = numStack.pop();//先弹出的是b String a = numStack.pop();//后弹出的是a String result = calculate(a,b,op); numStack.push(result);//结果入栈 progressStack.push(result);//中间结果入栈 } opStack.push(part); } } }//将表达式全数处理完,入栈 //将栈中剩余的内容计算完成 while (!opStack.empty()){ String op = opStack.pop();//弹出运算符 String b = numStack.pop();//先弹出的是b String a = numStack.pop();//后弹出的是a String result = calculate(a,b,op); numStack.push(result); progressStack.push(result);//中间结果入栈 } // System.out.println("答案:"+numStack.pop()); return progressStack;//过程栈记录了中间过程,栈顶是最终结果 } public static String calculate(String a,String b,String op) throws ZeroDivException, NegativeNumberException { String result = ""; switch (op){ case "+" : result = add(a,b);break; case "-" : result = sub(a,b);break; case "×" : result = mul(a,b);break; case "÷" : result = div(a,b);break; default:result="中间值"; } return result; }
public static int checkRepeat(List<MyBean> list, String result) { if (list == null || list.size() == 0) { return -1; } int left = 0;//左索引 int right = list.size() - 1;//右索引 String low = list.get(left).result; String high = list.get(right).result; try { String resultStr = CalculatorUtils.sub(result, low); int lowInt = CalculatorUtils.getInt(low); int highInt = CalculatorUtils.getInt(high); int gap = CalculatorUtils.getInt(resultStr); if (left == right) { return list.get(left).result.equals(result) ? left : -1; } int mid = left + gap * (right - left) / (highInt - lowInt); return select(list, left, right, mid, result); } catch (Throwable e) { return -1; } }
测试计算过程有负数出现
public void testCalculate1() throws ZeroDivException, NegativeNumberException { MathUtils.setNumRange(10); String expression = "9’2/9 - 10’4/5 + 9 - 2’2/3 ="; try { System.out.print(expression); System.out.print(CalculatorUtils.calculate(expression)); System.out.println(); }catch (NegativeNumberException e){ System.out.println(e.getMessage()); } }
测试是否为一个合法数字
public void testIsNum() { System.out.println(ExpressionUtils.isNum("12#/2")); System.out.println(ExpressionUtils.isNum("12/2")); System.out.println(ExpressionUtils.isNum("1’2/82")); System.out.println(ExpressionUtils.isNum("12/2’3")); System.out.println(ExpressionUtils.isNum("12/2/3")); System.out.println(ExpressionUtils.isNum("1’22’3")); System.out.println(ExpressionUtils.isNum("1’2/2’3")); System.out.println(ExpressionUtils.isNum("")); System.out.println(ExpressionUtils.isNum("1’/2")); System.out.println(ExpressionUtils.isNum("1")); System.out.println(ExpressionUtils.isNum("33")); System.out.println(ExpressionUtils.isNum("/1")); System.out.println(ExpressionUtils.isNum("1’’//")); }
测试加法
public void testAdd() { try { System.out.println(CalculatorUtils.add("4’6/3","3’2/3")); } catch (ZeroDivException e) { e.printStackTrace(); } }
测试减法
public void testSub() { try { System.out.println(CalculatorUtils.sub("3’1/2","3’3/5")); } catch (ZeroDivException | NegativeNumberException e) { e.printStackTrace(); } try { System.out.println(CalculatorUtils.sub("4’1/2","3’3/5")); } catch (ZeroDivException | NegativeNumberException e) { e.printStackTrace(); } }
测试乘法
public void testMul() { try { System.out.println(CalculatorUtils.mul("2’3/5","3/5")); } catch (ZeroDivException e) { e.printStackTrace(); } }
测试除法
public void testDiv(){ try { System.out.println(CalculatorUtils.div("3/5","2/5")); } catch (ZeroDivException e) { e.printStackTrace(); } }
测试生成合法的随机数
public void testGetNum() { MathUtils.setNumRange(10); for (int i = 0;i<10;i++){ System.out.println(MathUtils.getNum()); } }
测试生成的符号
public void testGetOperation() { for (int i = 0;i<10;i++){ System.out.println(MathUtils.getOperation()); } }
测试生成的表达式
public void testGetExpression() { MathUtils.setNumRange(10); for (int i = 0;i<10;i++) { System.out.println(ExpressionUtils.getExpression()); } }
测试表达式是否合法
public void testCheck() { boolean flag; flag = ExpressionUtils.check("1 ÷ 2’9/10 = "); System.out.println(flag); }