练习5.1——四则运算 测试与封装(更新版)
主函数:
1 package h2; 2 3 import java.text.DecimalFormat; 4 import java.util.Scanner; 5 import java.util.regex.Pattern; 6 7 import Excep.YichangException; 8 /* 9 * 1.定制数量 10 * 2.控制是否有乘除法 11 * 3.控制数值范围 12 * 4.定制真分数练习题 13 * 5.校检用户输入 14 * 6.输出答题正确率 15 */ 16 public class Main { 17 public static int max = 10;// 控制算式个数 18 public static String[] staticanser = new String[max];// 标准答案 19 public static DecimalFormat decimal = new DecimalFormat("#.##"); 20 21 22 // 求最大公约数 23 private static int calcMaxSubmultiple(int num1, int num2) { 24 num1=Math.abs(num1);//防止负数时求不得最大公约数。 25 num2=Math.abs(num2); 26 int min = Math.min(num1, num2); 27 int maxSubmultiple = 1; 28 for (int i = min; i >= 1; i--) { 29 if (num1 % i == 0 && num2 % i == 0) 30 { 31 maxSubmultiple = i; 32 break; 33 } 34 35 } 36 return maxSubmultiple; 37 } 38 //主函数 39 public static void main(String[] args) { 40 41 char[] op = { ' ', '+', '-', '*', '/' };// 操作符 42 int[] no = new int[4];// 操作符地址 43 int useno = 0;// 控制操作符 44 int n = 3;// 操作数个数(随机) 45 int[] num1 = new int[10];// 操作数 46 char opp;// 判断是否需要乘除法 47 char real;// 判断是否需要真分数的题目 48 int[] cs = { 1, 100 };// 数值范围 49 String[] useranser = new String[max];// 用户输入的答案 50 51 52 int f = 0;// 控制输出真分数的操作符 53 int count = 0;// 统计答题正确的数量 54 55 int s1 = 1;// 分子通分 56 int ss1 = 1;// 分子通分 57 int s2 = 1;// 分母通分 58 int result = 0;// 分子计算 59 int gys;// 最大公约数 60 int ff = 0;// 分数除法,分子为0标志位 61 int fff=0;// 62 String zjfz = new String();// 最简分子 63 String zjfm = new String();// 最简分母 64 Pattern pattern = Pattern.compile("[0-9]*"); // 限定输入算式数量输入的必须是数字 65 66 Scanner in = new Scanner(System.in); 67 //定制要求 68 System.out.print("请输入需定制的算式数量(1-20):");// 1.定制数量 69 do { 70 String str = in.nextLine(); 71 if (pattern.matcher(str).matches()) {// 如果输入的是数字就执行 72 max = Integer.parseInt(str); 73 if(max<=20&&max>0) 74 { 75 break; 76 } 77 else 78 { 79 System.out.print("你输入的范围有误,请重新输入:"); 80 } 81 82 } else { 83 System.out.print("你输入的不是数字,请重新输入:"); 84 } 85 } while (true); 86 87 88 System.out.print("是否需要乘除法(Y/N):");// 2.控制乘除参数 89 do { 90 opp = in.next().charAt(0); 91 if (opp == 'Y' || opp == 'y') { 92 useno = 4; 93 break; 94 } else if (opp == 'N' || opp == 'n') { 95 useno = 2; 96 break; 97 } else { 98 System.out.print("输入错误,请重新输入:"); 99 } 100 } while (true); 101 102 System.out.print("参数范围(eg:1,100):");// 3.控制数值范围 103 String str = new String(); 104 int sr = 0;//判断循环结束 105 in.nextLine();// 过滤掉上面.next()方面的回车。 106 do { 107 try { 108 str = in.nextLine(); 109 String[] ss = new String[2]; 110 ss = str.split(","); 111 cs[0] = Integer.valueOf(ss[0]); 112 cs[1] = Integer.valueOf(ss[1]); 113 sr = 1; 114 } catch (Exception e) { 115 System.out.print("输入格式错误,请重新输入:"); 116 } 117 } while (sr != 1); 118 119 120 System.out.print("是否增加真分数练习题(Y/N):");// 4.真分数题目 121 do { 122 real = in.next().charAt(0); 123 if ( real == 'Y' || real == 'y') { 124 125 break; 126 } else if ( real == 'N' || real == 'n') { 127 break; 128 } else { 129 System.out.print("输入错误,请重新输入:"); 130 } 131 } while (true); 132 133 //----------------题目----------------------- 134 System.out.println(); 135 System.out.println(" 2014-2015学年度第一单元测试卷"); 136 System.out 137 .println("班级: 姓名: 座号: 得分: "); 138 System.out.println(); 139 System.out.println("一、请认真仔细地计算下面各题。(小数请保留小数点后两位)"); 140 System.out.println(); 141 Core c1=new Core(); 142 for (int i = 0; i < max; i++) { 143 144 System.out.print("(" + (i + 1) + ") "); 145 n = (int) (Math.random() * 4 + 2);// 2-5个操作数 146 for (int j = 0; j < n; j++) { 147 num1[j] = (int) (Math.random() * (cs[1] - cs[0]) + cs[0]);// 控制随机数数值 148 } 149 for (int k = 0; k < n - 1; k++) { 150 no[k] = (int) (Math.random() * useno + 1);// 随机产生操作符 151 if(no[k]==4&&num1[k+1]==0){ 152 do{ 153 num1[k+1]=(int) (Math.random() * (cs[1] - cs[0]) + cs[0]);//如果除号后为0,则重新取数。 154 }while(num1[k+1]==0); 155 } 156 } 157 for (int h = 0; h < n; h++) { 158 if (h != n - 1) { 159 if(num1[h]<0) 160 { 161 System.out.print("("+num1[h]+")"); 162 System.out.print(op[no[h]]); 163 } 164 else{ 165 System.out.print(num1[h]); 166 System.out.print(op[no[h]]); 167 } 168 } else { 169 if(num1[h]<0) 170 { 171 System.out.print("("+num1[h]+")="); 172 } 173 else 174 System.out.print(num1[h] + "="); 175 } 176 } 177 System.out.println(); 178 c1.calcute(num1, op, no, n); 179 } 180 181 182 183 184 185 186 // 学生答题模块 187 System.out.println("==================答题分割线========================="); 188 for (int i = 0; i < max; i++) { 189 System.out.print((i + 1) + ":"); 190 useranser[i]=in.next(); 191 if (useranser[i].equalsIgnoreCase(staticanser[i])) { 192 count++; 193 } 194 } 195 System.out.println("标准答案为:"); 196 for (int i = 0; i < max; i++) { 197 System.out.println((i + 1) + ":" + staticanser[i]); 198 } 199 System.out.println("答题正确率为:" + String.valueOf(decimal.format(((float) count / (float) max) * 100)) 200 + "%"); 201 System.out.println("==================答题分割线========================="); 202 203 //真分数 204 if (real == 'Y' || real == 'y') { 205 System.out.println("二、请计算下列真分数算式。(无法计算请填null)"); 206 System.out.println(); 207 for (int i = 0; i < max; i++) { 208 System.out.print("(" + (i + 1) + ") "); 209 for (int j = 0; j < 2; j++)// (第一个真分数) 210 { 211 num1[j] = (int) (Math.random() * (cs[1] - cs[0]) + cs[0]);// 控制随机数数值 212 if (j == 1 ) { 213 while (num1[j - 1] >num1[j]||num1[j]== 0) { 214 num1[j] = (int) (Math.random() * (cs[1] - cs[0]) + cs[0]);// 控制随机数数值 215 } 216 } 217 } 218 for (int j = 2; j < 4; j++)// (第二个真分数) 219 { 220 num1[j] = (int) (Math.random() * (cs[1] - cs[0]) + cs[0]);// 控制随机数数值 221 if (j == 3) { 222 while (num1[j - 1] >num1[j]||num1[j]== 0) { 223 num1[j] = (int) (Math.random() * (cs[1] - cs[0]) + cs[0]);// 控制随机数数值 224 } 225 } 226 } 227 228 for (int k = 0; k < 1; k++) {// 符号个数 229 no[k] = (int) (Math.random() * useno + 1);// 随机产生操作符 230 } 231 for (int h = 0; h < 4; h++) {// 2个真分数 232 if (h % 2 == 0) 233 System.out.print(("(" + num1[h] + "/")); 234 else if (h % 2 == 1) { 235 System.out.print(num1[h] + ")"); 236 if (f < 1) {// 控制只输出一个操作符 237 System.out.print(op[no[f]]); 238 f++; 239 } else 240 System.out.println("="); 241 242 } 243 } 244 245 f = 0; 246 //计算第二大题标准答案 247 count=0; 248 249 } 250 251 // 答题模板 252 System.out.println("==================答题分割线========================="); 253 for (int i = 0; i < max; i++) { 254 System.out.print((i + 1) + ":"); 255 useranser[i] = in.next(); 256 if (useranser[i].equals(staticanser[i])) { 257 count++; 258 } 259 } 260 System.out.println("标准答案为:"); 261 for (int i = 0; i < max; i++) { 262 System.out.println((i + 1) + ":" + staticanser[i]); 263 } 264 System.out.println("答题正确率为:" + String.valueOf(decimal.format(((float) count / (float) max) * 100)) 265 + "%"); 266 System.out 267 .println("==================答题分割线========================="); 268 } 269 270 } 271 }
封装Core类实现计算功能:
1 package h2; 2 3 import Excep.YichangException; 4 5 public class Core { 6 int sign; // 累加运算时的符号 7 float left, right;// 保存蹭结果 8 int i = 0; 9 float result; 10 11 public void calcute(int[] num1, char[] op, int[] no, int n) 12 { 13 // 一个算式中的所有数字num1,符号op,随机产生的符号下标no,随机产生的算式操作数个数n. 14 // // 计算第一大题答案 15 for (int h = 0; h < n - 1; h++) { 16 if ((no[h] == 4) && (num1[h + 1] == 0)) { 17 throw new ArithmeticException(); 18 } 19 } 20 left = 0; 21 right = num1[0]; 22 sign = 1; 23 for (int g = 0; g < n - 1; g++) { 24 switch (op[no[g]]) { 25 case '+': 26 left = left + sign * right; 27 sign = 1; 28 right = num1[g + 1]; 29 break; 30 case '-': 31 left = left + sign * right; 32 sign = -1; 33 right = num1[g + 1]; 34 break; 35 case '*': 36 right = right * num1[g + 1]; 37 break; 38 case '/': 39 right = right / num1[g + 1]; 40 break; 41 } 42 } 43 result = left + sign * right; 44 Main.staticanser[i] = String.valueOf(Main.decimal.format(left+ sign * right)); 45 i++; 46 } 47 48 public float getResult() { 49 return this.result; 50 } 51 }
测试类:
1 package h1; 2 3 import static org.junit.Assert.*; 4 5 import org.junit.Assert; 6 import org.junit.Test; 7 8 import Excep.YichangException; 9 import h2.Core; 10 11 public class CoreTest { 12 @Test 13 public void testAdd() {// 加法 14 int n = 3;// 操作数个数 15 int[] num1 = { 1, 2, 3 };// 操作数 16 char[] op = { ' ', '+', '-', '*', '/' };// 操作符 17 int[] no = { 1, 1 };// 操作符下标 18 Core c = new Core(); 19 c.calcute(num1, op, no, n); 20 float r = c.getResult(); 21 System.out.println(r); 22 assertEquals(6, r, 0.1); 23 } 24 25 @Test 26 public void testJian() {// 减法 27 int n = 3;// 操作数个数 28 int[] num1 = { 1, 2, 3 };// 操作数 29 char[] op = { ' ', '+', '-', '*', '/' };// 操作符 30 int[] no = { 2, 2 };// 操作符下标 31 Core c = new Core(); 32 c.calcute(num1, op, no, n); 33 float r = c.getResult(); 34 System.out.println(r); 35 assertEquals(-4, r, 0.1); 36 } 37 38 @Test 39 public void testMulti() {// 乘法 40 int n = 3;// 操作数个数 41 int[] num1 = { 2, 2, 3 };// 操作数 42 char[] op = { ' ', '+', '-', '*', '/' };// 操作符 43 int[] no = { 3, 3 };// 操作符下标 44 Core c = new Core(); 45 c.calcute(num1, op, no, n); 46 float r = c.getResult(); 47 System.out.println(r); 48 assertEquals(12, r, 0.1); 49 } 50 51 @Test 52 public void testDiv() {// 除法 53 int n = 2;// 操作数个数 54 int[] num1 = { 2, 4 };// 操作数 55 char[] op = { ' ', '+', '-', '*', '/' };// 操作符 56 int[] no = { 4 };// 操作符下标 57 Core c = new Core(); 58 c.calcute(num1, op, no, n); 59 float r = c.getResult(); 60 System.out.println(r); 61 assertEquals(0.5, r, 0.1); 62 } 63 64 @Test 65 public void testNormal() {// 混合运算 66 int n = 4;// 操作数个数 67 int[] num1 = { 1, 2, 3, 2 };// 操作数 68 char[] op = { ' ', '+', '-', '*', '/' };// 操作符 69 int[] no = { 1, 3, 4 };// 操作符下标 70 Core c = new Core(); 71 c.calcute(num1, op, no, n); 72 float r = c.getResult(); 73 System.out.println(r); 74 assertEquals(4, r, 0.1); 75 } 76 77 @Test(expected = ArithmeticException.class) 78 public void testZero() {// 除以零 79 int n = 3;// 操作数个数 80 int[] num1 = { 1, 0, 3 };// 操作数 81 char[] op = { ' ', '+', '-', '*', '/' };// 操作符 82 int[] no = { 4, 1 };// 操作符下标 83 Core c = new Core(); 84 c.calcute(num1, op, no, n); 85 } 86 87 @Test 88 public void dealZero() {// 除以零(处理异常) 89 int n = 3;// 操作数个数 90 int[] num1 = { 1, 0, 3 };// 操作数 91 char[] op = { ' ', '+', '-', '*', '/' };// 操作符 92 int[] no = { 4, 1 };// 操作符下标 93 Core c = new Core(); 94 try { 95 c.calcute(num1, op, no, n);// 运算1/0+3 96 } catch (Exception e) { 97 System.out.println("除数不能为0"); 98 } 99 } 100 101 102 @Test 103 public void testUnnormal2() {// 非法输入 104 int n = 4;// 操作数个数 105 int[] num1 = { 1, 2, 3, 2 };// 操作数 106 char[] op = { ' ', '+', '-', '*', '/' };// 操作符 107 int[] no = { 1, 3, 5};// 操作符下标--------越界 108 Core c = new Core(); 109 try { 110 c.calcute(num1, op, no, n);// 运算1+2*3/2 111 float r = c.getResult(); 112 System.out.println(r); 113 } catch (Exception e) { 114 System.out.println("下标越界,操作符下标越界"); 115 } 116 } 117 118 }
截图:
总结:
更新处理了一些奇怪的异常(操作数下标填了个5)。。以及除数为零异常。
用户输入部分未能封装成一个类,但异常处理都有。尝试过,但是出错很多。还没能彻底实现。在总的程序来看,调用Core类时其实是不会出现除数为零或者其他异常的。