需求分析
1、控制运算表达式题目数量,控制题目中数值的大小
2、题目中存在分数形式要进行约分
3、运算符个数不能超过3个
4、不能出现重复题目,即两个运算表达式的计算步骤不能完全相同
5、程序同时支持计算生成的每道题目,并对结果进行约分
6、对用户所做答案进行判断,并且输出正确答案或错误答案
功能设计
基本功能
1、根据控制台输入的数字随机生成指定运算元个数和算式数目的运算符
2、基本的四则运算功能
3、式子中的分数和最终计算结果均约分到最简
设计实现
环境
windows10+java
程序结构设计
程序设计
-
功能点1:生成随机数
随机数生成方法: public Num createNum(int range)
1 package method; 2 3 import java.util.Random; 4 import method.Num; 5 6 public class randomNum { 7 public Num createNum(int range) { 8 Num num = new Num(); 9 Random rand = new Random(); 10 int numerator = rand.nextInt(range + 1); 11 int denominator = rand.nextInt(10) + 1; 12 if (rand.nextInt(1) == 1) { 13 num.setNumerator(numerator); 14 num.setDenominator(1); 15 } else { 16 num.setNumerator(numerator); 17 num.setDenominator(denominator); 18 } 19 num = reduction(num); 20 return num; 21 } 22 23 public Num reduction(Num num) { 24 int numerator = num.getNumerator(); 25 int denominator = num.getDenominator(); 26 if (numerator == 0) { 27 num.setDenominator(1); 28 return num; 29 } 30 int divisor = getMaxDivisor(numerator, denominator); 31 if (divisor == 1) { 32 return num; 33 } else { 34 num.setNumerator(num.getNumerator() / divisor); 35 num.setDenominator(num.getDenominator() / divisor); 36 return num; 37 } 38 } 39 40 public int getMaxDivisor(int numerator, int denominator) { 41 if (denominator == 0) { 42 return numerator; 43 } else { 44 return getMaxDivisor(denominator, numerator % denominator); 45 } 46 } 47 }
-
功能点2:生成随机运算符
随机运算符生成方法: public String createOperator()
1 package method; 2 3 import java.util.Random; 4 5 public class randomOperator { 6 public String createoperator() { 7 String operator = null; 8 Random rand = new Random(); 9 int n = rand.nextInt(4); 10 switch (n) { 11 case 0: 12 operator = "+"; 13 break; 14 case 1: 15 operator = "-"; 16 break; 17 case 2: 18 operator = "*"; 19 break; 20 case 3: 21 operator = "÷"; 22 break; 23 default: 24 operator = "+"; 25 break; 26 } 27 return operator; 28 } 29 }
-
功能点3:组成算数表达式
表达式表示: 类型:ArrayList 组成方法: public ArrayList<Object> createArithmetic(int range)
-
功能点4:计算表达式结果并输出文档
逆波兰式转换: public ArrayList<Object> toRPN(ArrayList<Object> list) 逆波兰式计算 public Num countRPN(ArrayList<Object> right) private Num twoResult(String is, Num op1, Num op2)
1 package method; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import method.Num; 6 import method.Stacks; 7 8 public class RPN { 9 public ArrayList<Object> toRPN(ArrayList<Object> list) { 10 ArrayList<Object> right = new ArrayList<Object>();// 存储右序表达式 11 Stacks aStack = new Stacks();// 栈 12 String operator; 13 int position = 0;// 当前指针位置 14 while (true) { 15 // 当前指针为符号 16 if (isOperator(list.get(position).toString())) { 17 // 栈为空,或指针为(,直接进栈 18 if (aStack.top == -1 19 || ((String) list.get(position)).equals("(")) { 20 aStack.push(list.get(position)); 21 } else { 22 // 指针为) 23 if (((String) list.get(position)).equals(")")) { 24 // 将栈内(后的运算符出栈 25 while (true) { 26 if (aStack.top != -1 27 && !((String) aStack.top()).equals("(")) { 28 operator = (String) aStack.pop(); 29 right.add(operator); 30 } else { 31 if (aStack.top != -1) 32 aStack.pop(); 33 break; 34 } 35 } 36 } else { 37 while (true) { 38 // 栈不为空,判断优先级 39 if (aStack.top != -1 40 && priority((String) list.get(position), 41 (String) aStack.top())) { 42 operator = (String) aStack.pop(); 43 if (!operator.equals("(")) 44 right.add(operator); 45 } else { 46 break; 47 } 48 49 } 50 aStack.push(list.get(position)); 51 } 52 } 53 } 54 // 数字入栈 55 else { 56 right.add(list.get(position)); 57 } 58 position++; 59 if (position >= list.size()) 60 break; 61 } 62 // 栈内剩余运算符出栈 63 while (aStack.top != -1) { 64 operator = (String) aStack.pop(); 65 if (!operator.equals("(")) 66 right.add(operator); 67 } 68 return right; 69 } 70 71 // 判断是否为运算符 72 public static boolean isOperator(String operator) { 73 if (operator.equals("+") || operator.equals("-") 74 || operator.equals("*") || operator.equals("÷") 75 || operator.equals("(") || operator.equals(")")) 76 return true; 77 else 78 return false; 79 } 80 81 // 设置操作符号的优先级别 82 public static boolean priority(String operatorout, String operatorin) { 83 int m = 0, n = 0; 84 String addop[][] = { { "+", "-", "*", "÷", "(", ")" }, 85 { "+", "-", "*", "÷", "(", ")" } }; 86 int first[][] = { { 1, 1, 2, 2, 2, 0 }, { 1, 1, 2, 2, 2, 0 }, 87 { 1, 1, 1, 1, 2, 0 }, { 1, 1, 1, 1, 2, 0 }, 88 { 2, 2, 2, 2, 2, 0 }, { 2, 2, 2, 2, 2, 2 } }; 89 for (int i = 0; i < 6; i++) { 90 if (operatorin.equalsIgnoreCase(addop[0][i])) 91 m = i; 92 } 93 for (int i = 0; i < 6; i++) { 94 if (operatorout.equalsIgnoreCase(addop[1][i])) 95 n = i; 96 } 97 if (first[m][n] == 1) { 98 return true; 99 } else 100 return false; 101 } 102 103 // 逆波兰式计算 104 public Num countRPN(ArrayList<Object> right) { 105 // 栈 106 Stacks aStack = new Stacks(); 107 Num op1, op2, result = null; 108 String is = null; 109 Iterator<Object> it = right.iterator(); 110 111 while (it.hasNext()) { 112 Object ob = it.next(); 113 is = ob.toString(); 114 if (isOperator(is)) { 115 op2 = (Num) aStack.pop(); 116 op1 = (Num) aStack.pop(); 117 Num do_0 = twoResult(is, op1, op2); 118 if (do_0.getDenominator() == 0) { 119 return (new Num(-1, 1)); 120 } 121 aStack.push(do_0); 122 } else 123 aStack.push(ob); 124 } 125 result = (Num) aStack.pop(); 126 return result; 127 } 128 129 // 计算两个数 130 private Num twoResult(String is, Num op1, Num op2) { 131 // 结果数 132 Num result = new Num(); 133 randomNum f1 = new randomNum(); 134 // 获取分子分母 135 int n1 = op1.getNumerator(); 136 int d1 = op1.getDenominator(); 137 int n2 = op2.getNumerator(); 138 int d2 = op2.getDenominator(); 139 // 判断运算符 140 switch (is) { 141 case "+": 142 if (d1 != d2) { 143 n1 = n1 * d2; 144 n2 = n2 * d1; 145 d1 = d1 * d2; 146 d2 = d1; 147 result.setNumerator(n1 + n2); 148 result.setDenominator(d1); 149 result = f1.reduction(result); 150 } else { 151 result.setNumerator(n1 + n2); 152 result.setDenominator(d1); 153 result = f1.reduction(result); 154 } 155 break; 156 case "-": 157 if (d1 != d2) { 158 n1 = n1 * d2; 159 n2 = n2 * d1; 160 d1 = d1 * d2; 161 d2 = d1; 162 result.setNumerator(n1 - n2); 163 result.setDenominator(d1); 164 result = f1.reduction(result); 165 } else { 166 result.setNumerator(n1 - n2); 167 result.setDenominator(d1); 168 result = f1.reduction(result); 169 } 170 break; 171 case "*": 172 result.setNumerator(n1 * n2); 173 result.setDenominator(d1 * d2); 174 result = f1.reduction(result); 175 break; 176 case "÷": 177 if (n2 == 0) { 178 result = new Num(0, 0); 179 break; 180 } 181 result.setNumerator(n1 * d2); 182 result.setDenominator(d1 * n2); 183 result = f1.reduction(result); 184 break; 185 default: 186 break; 187 } 188 return result; 189 } 190 }
- 功能点5:比较答案
1 package method; 2 3 import java.util.ArrayList; 4 import java.util.Scanner; 5 6 import method.Arithmetic; 7 import method.RPN; 8 9 public class Main { 10 public static void main(String[] args){ 11 Arithmetic arithmetic = new Arithmetic(); 12 ArrayList<Object> list = arithmetic.createarithmetic(3); 13 for (int i = 0; i < list.size(); i++) { 14 System.out.print(list.get(i)); 15 } 16 RPN rpn = new RPN(); 17 ArrayList<Object> right = rpn.toRPN(list); 18 Num num = new Num(); 19 num = rpn.countRPN(right); 20 String a = num.toString(); 21 Scanner answer = new Scanner(System.in); 22 System.out.println(); 23 System.out.print("输入答案:"); 24 String name = answer.nextLine(); 25 if(name.equals(a)){ 26 System.out.println("正确 "); 27 }else{ 28 System.out.println("错误 "); 29 System.out.print("正确答案:" + a); 30 } 31 } 32 }
CODING地址:https://coding.net/u/hydralwz/p/size/git
PSP记录表
PSP2.1 | Personal Software Process Stages | Time Senior Student | Time |
Planning | 计划 | 10 | 10 |
· Estimate | 估计这个任务需要多少时间 | 10 | 8 |
Development | 开发 | 158 | 324 |
· Analysis | 需求分析 (包括学习新技术) | 13 | 7 |
· Design Spec | 生成设计文档 | 17 | 8 |
· Design Review | 设计复审 | 5 | 3 |
· Coding Standard | 代码规范 | 10 | 21 |
· Design | 具体设计 | 20 | 50 |
· Coding | 具体编码 | 60 | 150 |
· Code Review | 代码复审 | 10 | 30 |
· Test | 测试(自我测试,修改代码,提交修改) | 20 | 20 |
Reporting | 报告 | 10 | NaN |
· | 测试报告 | 10 | NaN |
· | 计算工作量 | 10 | NaN |
· | 并提出过程改进计划 | 20 | NaN |