1.设计思想:
针对新的要求:是否有乘除法; 是否有括号(最多可以支持十个数参与计算); 数值范围; 加减有无负数; 除法有无余数!在创建新数组根据不同的需求进行选择。利用random随机生成操作数,构造运算式时添加“(”、“)”,创建expressCalculate方法进行计算,创建priorityCompare方法利用栈判断优先级。再创建随机生成括号和运算符的方法,构造Fenshu类,创建约简等方法。最后在main函数里根据创建的数组长度进行循环输出。
2.源代码:
import java.util.Random; import java.util.Scanner; import java.util.Stack; public class SiZe1 { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scan = new Scanner(System.in); System.out.println("0、整数式 1、分数式"); int type = scan.nextInt(); System.out.println("生成的运算式个数:"); int n = scan.nextInt(); System.out.println("是否有乘除法(1有,0没有)"); int hasChengChu = scan.nextInt(); System.out.println("是否有括号(1有,0没有)"); int hasKuoHao = scan.nextInt(); System.out.println("加减有无负数(1有,0没有)"); int hasFuShu = scan.nextInt(); System.out.println("除法有无余数(1有,0没有)"); int hasYuShu = scan.nextInt(); System.out.println("数值范围(最大数)"); int maxNum = scan.nextInt(); String[] yunSuanShiArray = createYunSuanShi(hasChengChu, hasKuoHao, hasFuShu, hasYuShu, maxNum, n, type); for(int i = 0;i < yunSuanShiArray.length;i++){ System.out.println(yunSuanShiArray[i]); } scan.close(); } //生成整数计算式添加限制条件,type为运算式类型 0代表整数式,1代表真分数式 public static String[] createYunSuanShi(int hasChengChu,int hasKuoHao,int hasFuShu,int hasYuShu,int maxNum,int n,int type) { int i = 0; String yunSuanShiTemp; String[] yunSuanShiArray = new String[n]; int operatorScope = 2 + 2 * hasChengChu;//运算符范围,2或4,2代表只有加减,4代表有加减乘除 int length; String[] operatorArray = {"+","-","*","/"}; String[] operatorNum = null;//存储运算数 int num_index;//运算数下标 String[] operatorSymbol = null;//存储运算符 int symbol_index;//运算符下标 int[] brackets = null;//存储括号个数 while(i < n) { length = Integer.parseInt(getOperatorNumber(0, 9)) + 2;//计算式运算数长度 operatorNum = new String[length]; operatorSymbol = new String[length - 1]; num_index = 0; symbol_index = 0; operatorNum[num_index++] = getOperatorNumber(type, maxNum);//随机生成操作数 for(int j = 0;j < length - 1;j++){ operatorSymbol[symbol_index++] = operatorArray[Integer.parseInt(getOperatorNumber(0, operatorScope))];//随机生成操作符 operatorNum[num_index++] = getOperatorNumber(type, maxNum);//随机生成操作数 } if(hasKuoHao == 1){ brackets = randomAddBracket(length);//生成括号数组 } //构造运算式 yunSuanShiTemp = ""; for(int j = 0;j < length;j++){ //添加左括号 if(hasKuoHao == 1){ for(int k = 0;k < brackets[j];k++){ yunSuanShiTemp += "("; } } yunSuanShiTemp += " " + operatorNum[j] + " ";//加上运算数 //添加右括号 if(hasKuoHao == 1){ for(int k = 0;k > brackets[j];k--){ yunSuanShiTemp += ")"; } } //如果不是最后一个运算数则要加上运算符 if(j != length - 1){ yunSuanShiTemp += operatorSymbol[j]; } } //计算结果 String answer = expressCalculate(yunSuanShiTemp, hasFuShu, hasYuShu, type, length - 1); if((answer.equals("ERROR"))){ continue; } yunSuanShiTemp += "=" + answer; //检验重复 boolean chongFu = false; for(int j = 0;j < i;j++){ if((yunSuanShiArray[j].equals(yunSuanShiTemp))){ chongFu = true; break; } } if(chongFu == false){ yunSuanShiArray[i++] = yunSuanShiTemp; } } return yunSuanShiArray; } //表达式计算,参数为字符串类型的运算式 public static String expressCalculate(String express,int hasFuShu,int hasYuShu,int type,int symbolNum){ Stack<String> num = new Stack<String>(); Stack<String> symbolS = new Stack<String>(); symbolS.push("#"); express += "#"; char ch; int i = 0; int s = 0; ch = express.charAt(i); while(s < symbolNum){ if(ch == ' '){//读到空格,说明开始读运算数 String readNumStr = ""; while(true){ ch = express.charAt(++i); if(ch == ' '){ break; } readNumStr += ch; } if((i + 1) < express.length()){ ch = express.charAt(++i); } num.push(readNumStr); }else{//读到的是运算符 char compare = priorityCompare(symbolS.peek(),ch + ""); if(compare == '='){//如果是右括号 symbolS.pop(); ch = express.charAt(++i); }else if(compare == '>'){//ch的优先级小于栈顶的优先级 比栈顶的优先级高就不算,入栈,低就弹栈运算 //弹出两个运算数,弹出一个运算符 String bStr = num.pop(); String aStr = num.pop(); String symbolT = symbolS.pop(); String c = yunSuan(aStr,bStr,symbolT,hasFuShu,hasYuShu,type); if(c.equals("ERROR")){ return "ERROR"; }else if(c.indexOf("余") >= 0 && s != symbolNum - 1){//有余数 return "ERROR"; }else{ num.push(c); } s++; }else{ symbolS.push(ch + ""); if((i + 1) < express.length()){ ch = express.charAt(++i); } } } } return num.pop(); } public static String yunSuan(String aStr,String bStr,String symbol,int hasFuShu,int hasYuShu,int type){ if(type == 0){//整数 int a = Integer.parseInt(aStr); int b = Integer.parseInt(bStr); if(symbol.equals("+")){ return "" + (a + b); }else if(symbol.equals("-")){ if(a - b < 0 && hasFuShu == 0){ return "ERROR"; }else{ return "" + (a - b); } }else if(symbol.equals("*")){ return "" + (a * b); }else{ if(b == 0){ return "ERROR"; } if(a % b == 0){ return "" + (a / b); }else{ if(hasYuShu == 1){ return (a / b) + "余" + (a % b); }else{ return "ERROR"; } } } }else{//分数 String[] af = aStr.split("/"); String[] bf = bStr.split("/"); if(af[0].equals("0") || bf[0].equals("0")){ return "ERROR"; } FenShu a = new FenShu(Integer.parseInt(af[1]),Integer.parseInt(af[0])); FenShu b = new FenShu(Integer.parseInt(bf[1]),Integer.parseInt(bf[0])); if(symbol.equals("+")){ return a.add(b).toString(); }else if(symbol.equals("-")){ FenShu c = a.subtract(b); if(hasFuShu == 1 && c.getNumerator() < 0){ return "ERROR"; } return c.toString(); }else if(symbol.equals("*")){ return a.multiply(b).toString(); }else{ return a.divide(b).toString(); } } } //判断优先级 public static char priorityCompare(String a,String b){ char[][] priority = { {'>','>','<','<','<','>','>'}, {'>','>','<','<','<','>','>'}, {'>','>','>','>','<','>','>'}, {'>','>','>','>','<','>','>'}, {'<','<','<','<','<','=','>'}, {'>','>','>','>',' ','>','>'}, {'<','<','<','<','<',' ','='} }; int a_index = index_symbol(a); int b_index = index_symbol(b); return priority[a_index][b_index]; } public static int index_symbol(String a){ String p = "+-*/()#"; return p.indexOf(a); } //随机生成括号,参数为运算式的运算数的个数 public static int[] randomAddBracket(int length){ int[] brackets = new int[length]; for(int i = 0;i < brackets.length;i++) brackets[i] = 0; Random rd = new Random(); for(int i = 2;i < length;i++){//添加的括号长度(括号包围的运算数的个数) for(int j = 0;j < length - i + 1;j++){ int t = rd.nextInt(2);//随机生成0或1,0代表不加括号,1代表加括号 if(t == 1){ if(brackets[j] >= 0 && brackets[j + i - 1] <= 0){//要加的括号的第一个运算数周围没有右括号,且 最后一个运算数周围没有左括号 int counteract = 0; for(int k = j;k < j + i;k++){//将要加的括号之间的所有运算数对应的brackets相加, //如果和为0说明这个括号之间的括号是匹配的,不会出现括号交叉现象 counteract += brackets[k]; } if(counteract == 0){ brackets[j]++; brackets[j + i - 1]--; } } } } } return brackets; } //随机生成一个运算数( type==0代表生成整数,type==1代表生成真分数,maxNum代表数值范围 0-(maxNum-1) ) public static String getOperatorNumber(int type,int maxNum){ Random rd = new Random(); int a; while(true){ a = rd.nextInt(maxNum); if(type == 0){//随机生成一个整数 return "" + a; }else{//随机生成一个真分数 if(a == 0){ continue; } int b = rd.nextInt(a); FenShu c = new FenShu(a,b); return c.toString(); } } } } class FenShu { private int denominator,numerator; public int getDenominator() { return denominator; } public void setDenominator(int denominator) { this.denominator = denominator; } public int getNumerator() { return numerator; } public void setNumerator(int numerator) { this.numerator = numerator; } public FenShu(int denominator, int numerator) { this.denominator = denominator; this.numerator = numerator; yueJian(); } FenShu(){} //约简 public void yueJian(){ int y = 1; for(int i = numerator;i > 1;i--){ if(numerator % i == 0 && denominator % i == 0){ y = i; break; } } // int nc = numerator,dc = denominator; // if(nc != 0){ // while(nc != dc - nc){ // y = dc - nc; // if(nc > y){ // dc = nc; // nc = y; // }else{ // dc = y; // } // } // y = nc; // numerator /= y; denominator /= y; } //加 public FenShu add(FenShu b){ FenShu c = null; int nNumerator = this.numerator * b.getDenominator() + this.denominator * b.getNumerator(); int nDenominator = this.denominator * b.getDenominator(); c = new FenShu(nDenominator,nNumerator); return c; } //减 public FenShu subtract(FenShu b){ FenShu c = null; int nNumerator = this.numerator * b.getDenominator() - this.denominator * b.getNumerator(); int nDenominator = this.denominator * b.getDenominator(); c = new FenShu(nDenominator,nNumerator); return c; } //乘 public FenShu multiply(FenShu b){ FenShu c = null; int nNumerator = this.numerator * b.getNumerator(); int nDenominator = this.denominator * b.getDenominator(); c = new FenShu(nDenominator,nNumerator); return c; } //除 public FenShu divide(FenShu b){ FenShu c = null; int nNumerator = this.numerator * b.getDenominator(); int nDenominator = this.denominator * b.getNumerator(); c = new FenShu(nDenominator,nNumerator); return c; } //输出分数形式 public String toString(){ if(numerator != 0){ // if(numerator % denominator == 0) // return "" + numerator / denominator; return numerator + "/" + denominator; } return "0"; } }
3.运行结果截图
项目计划总结:
日期任务 | 听课 | 编写程序 | 查阅资料 | 日总计 |
星期一 | 2 | 2 | 1 | 4 |
星期二 | 1 | 1 | ||
星期三 | 2 | 1 | 3 | |
星期四 | 2 | 2 | 4 | |
星期五 | 3 | 1 | 4 | |
星期六 | 3 | 5 | ||
星期日 | ||||
周总计 | 4 | 12 | 4 |
21 |
时间记录日志:
日期 | 开始时间 | 结束时间 | 中断时间 | 静时间 | 活动 | 备注 |
3/7 | 14:00 | 15:50 | 10 | 100 | 编写 | 编写程序 |
19:30 | 21:30 | 20 | 100 | 编写 | 编写程序 | |
3/8 | 19:20 | 21:30 | 10 | 120 | 编写 | 编写程序 |
3/9 | ||||||
19:20 | 20:00 | 0 | 40 | 编写 | ||
3/10 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程 |
19:20 | 20:20 | 60 | 编写 | 调试程序 | ||
3/11 | 18:10 | 21:30 | 20 | 100 | 编写 | 调试程序 |
3/12 | ||||||
16:00 | 17:00 | 60 | 博客 | 撰写博客 |
缺陷记录日志:
日期 | 编号 | 引入阶段 | 排除阶段 | 修复时间&问题描述 |
3/7 | 1 | 编码 | 编译 | 30min,理清分数 |
3/8 | ||||
3/9 | ||||
3/10-3/11 | 2 | 编码 | 编译 | 2hour,调试调试 |
3/11-3/12 | 3 | 编码 | 编译 | 2hour,完善括号 |