:结对项目--四则运算
成员:林莉 宫丽君
经过课上同学的讲解,知道用中缀表达式转化为后缀表达式这种方法可以提高效率,做法如下:
1 Cal c1=new Cal(); 2 String inBefore = "1+2*3"; 3 String[] in = inBefore.split("") ; 7 public void testSolveOrder() { 8 HashMap<String, Integer> precedence = new HashMap<String, Integer>(); 9 precedence.put("(", 0); 10 precedence.put(")", 0); 11 precedence.put("+", 1); 12 precedence.put("-", 1); 13 precedence.put("*", 2); 14 precedence.put("/", 2); 15 assertEquals("123*+", c1.SolveOrder(in, precedence)); 16 fail("Not yet implemented"); 17 }
根据后缀(逆波兰式)计算
1 public double calculateOut(String[] out) { 2 //假设满足逆波兰式的输出不为空却长度不为零 3 assert (out != null && out.length != 0); 4 //操作数栈 5 Stack<Double> stack = new Stack<Double>(); 6 for (int i = 0; i < out.length; i++) { 7 if (isNumber(out[i])) { 8 stack.push(Double.parseDouble(out[i])); 9 } else { 10 double v1 = stack.pop(); 11 double v2 = stack.pop(); 12 double result = eval(out[i], v2, v1); 13 stack.push(result); 14 } 15 } 16 return stack.pop(); 17 }
想要产生括号且必须得成对出现,由于是四位数计算,所以穷举出括号的方式获取括号,rand()%5+1生成1-5之间的随机整数,然后选择括号类型。
1 switch(rand()%5) 2 { 3 4 case 1: s = "("+itos(n1)+ope[op1]+itos(n2)+")"+ope[op2]+itos(n3)+ope[op3]+itos(4);break; 5 case 2: s = "("+itos(n1)+ope[op1]+itos(n2)+ope[op2]+itos(n3)+")"+ope[op3]+itos(4);break; 6 case 3: s = itos(n1)+ope[op1]+"("+itos(n2)+ope[op2]+itos(n3)+")"+ope[op3]+itos(4);break; 7 case 4: s = itos(n1)+ope[op1]+"("+itos(n2)+ope[op2]+itos(n3)+ope[op3]+itos(4)+")";break; 8 case 5: s = "("+itos(n1)+ope[op1]+itos(n2)+")"+ope[op2]+"("+itos(n3)+ope[op3]+itos(4)+")";break; 9 10 }
测试是否是数字:
1 @Test 2 public void testIsNumber() { 3 assertEquals("1", "1"); 4 assertEquals("0", "+"); 5 }
测试单步计算结果:
1 @Test 2 public void testEval() { 3 assertEquals("5", c1.eval("+", 3, 2)); 4 assertEquals("6", c1.eval("*", 3, 2)); 5 assertEquals("1", c1.eval("-", 3, 2)); 6 assertEquals("2", c1.eval("/", 6, 3)); 7 }
部分代码如下:
1 // 中缀转后缀 2 public String[] SolveOrder(String[] in, HashMap<String, Integer> precedence) { 3 // 符合逆波兰式(后缀)的输出 4 int kk=in.length; 5 String out[] = new String[kk]; 6 int p = 0 ; 7 // 操作符 8 Stack<String> ops = new Stack<String>(); 9 for (int i = 0; i < in.length; i++) { 10 String s = in[i]; 11 // 碰见数值 就放进out数组末尾 12 if (!precedence.containsKey(in[i])) { 13 out[p] = s ; 14 p ++ ; 15 continue; 16 } 17 //如果优先级比栈顶的大 18 if (ops.isEmpty() || (precedence.get(s) > precedence.get(ops.peek()))) { 19 ops.push(s); 20 //break; 21 }else{ 22 //如果栈顶的比目前的运算符优先级小或者相等 一直出栈到没有或者栈顶 小于当前运算符 23 while (true ) { 24 ops.pop();// 出栈得运算符 25 out[p] = s ; 26 p ++ ; 27 if(ops.empty()) break ;//如果栈空了 break 28 if(precedence.get(ops.peek()) < precedence.get(s)){ 29 break ;//栈顶小于当前的了 break 30 } 31 } 32 out[p] = s ; 33 p ++ ; 34 } 35 } 36 // 若操作符栈不为空,就依次将剩余的操作符放入out数组 37 while (!ops.isEmpty()) { 38 out[p] = ops.peek() ; 39 p ++ ; 40 ops.pop() ; 41 } 42 return out; 43 } 44 45 // 优先级的定义 46 public HashMap<String, Integer> priorityInfo() { 47 HashMap<String, Integer> precedence = new HashMap<String, Integer>(); 48 precedence.put("(", 0); 49 precedence.put(")", 0); 50 precedence.put("+", 1); 51 precedence.put("-", 1); 52 precedence.put("*", 2); 53 precedence.put("/", 2); 54 return precedence; 55 } 56 57 public double calculateOut(String[] out) { 58 // 假设满足逆波兰式的输出不为空却长度不为零 59 int kk=out.length; 60 System.out.println("转换成后缀表达式是"); 61 for(int o=0;o<kk;o++){ 62 System.out.print(out[o]); 63 } 64 System.out.println(); 65 assert (out != null && out.length != 0); 66 // 操作数栈 67 Stack<Double> stack = new Stack<Double>(); 68 for (int i = 0; i < out.length; i++) { 69 if (isNumber(out[i])) { 70 stack.push(Double.parseDouble(out[i])); 71 } else { 72 double v1 = stack.pop(); 73 double v2 = stack.pop(); 74 double result = eval(out[i], v2, v1); 75 stack.push(result); 76 } 77 } 78 return stack.pop(); 79 } 80 81 // 判别是否是数字 82 public boolean isNumber(String s) { 83 if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) 84 return false; 85 return true; 86 } 87 88 public static double eval(String op, double val1, double val2) { 89 if (op.equals("+")) 90 return val1 + val2; 91 if (op.equals("-")) 92 return val1 - val2; 93 if (op.equals("/")) 94 return val1 / val2; 95 if (op.equals("*")) 96 return val1 * val2; 97 throw new RuntimeException("Invalid operator"); 98 } 99 public static void main(String[] args) { 100 System.out.println("请输入要计算的算式:"); 101 Scanner sc = new Scanner(System.in); 102 String inBefore = sc.nextLine(); 103 String[] in = inBefore.split("") ; 104 int kk=in.length; 105 System.out.println("您输入的算式是"); 106 for(int o=0;o<kk;o++){ 107 System.out.print(in[o]); 108 } 109 System.out.println(); 110 Cal cc = new Cal() ; 111 HashMap<String, Integer> precedence = cc.priorityInfo(); 112 String[] out = cc.SolveOrder(in, precedence); 113 System.out.println("所输入的算式结果为:" + cc.calculateOut(out)); 114 115 }