软件工程概论作业二

题目:

设计思想:

生成运算式:用随机数产生2-10之间的数当做运算式的长度,再随机产生相应个数的随机数当做运算数,随机产生0-1或0-3当做运算符。

因为要产生的随机数分为整数和分数,所以讲产生随机数的功能封装为一个函数,代码如下:

 1     //随机生成一个运算数(                type==0代表生成整数,type==1代表生成真分数,maxNum代表数值范围 0-(maxNum-1)               )
 2     public static String getOperatorNumber(int type,int maxNum){
 3         Random rd = new Random();
 4         int a;
 5         while(true){
 6             a = rd.nextInt(maxNum);
 7             if(type == 0){//随机生成一个整数
 8                 return "" + a;
 9             }else{//随机生成一个真分数
10                 if(a == 0){
11                     continue;
12                 }
13                 int b = rd.nextInt(a);
14                 FenShu c = new FenShu(a,b);
15                 return c.toString();
16             }
17         }
18     }
19     

 

随机产生括号:

假设运算式的运算数个数为n,则定义一个长度为n的整型数组 a,第i个元素对应第i个运算数,最后根据第i个数组元素的值来判断第i个运算数周围有什么括

(0代表没有括号,+s代表有s个左括号,-s代表有s个右括号)

则可以产生的括号的长度(即括号包围的运算数的个数)为2 ~ (n-1),

利用for循环控制括号的长度,循环变量 i 为2 ~ (n - 1)

循环体是另一个循环,循环变量 j 为0 ~ (n - i + 1)   (即可以加左括号的运算数的位置)

 内层循环循环体为:随机生成0或1,1代表加括号,但是还要判断在这是否可以加括号,如果a[j] >=0 (即这个运算数这没有右括号) 且 a[j + i - 1] <= 0

(即产生的这个括号的右括号的那个运算数周围没有左括号) 且 sum(a[j] ...... a[j + i - 1]) == 0  (即要加的这个括号之间的括号必须全部匹配,不能因为加上这个括号产生括号交叉现象)

代码为:

 

 1 //随机生成括号,参数为运算式的运算数的个数
 2     public static int[] randomAddBracket(int length){
 3         int[] brackets = new int[length];
 4         for(int i = 0;i < brackets.length;i++)   brackets[i] = 0;
 5         Random rd = new Random();
 6         for(int i = 2;i < length;i++){//添加的括号长度(括号包围的运算数的个数)
 7             for(int j = 0;j < length - i + 1;j++){
 8                 int t = rd.nextInt(2);//随机生成0或1,0代表不加括号,1代表加括号
 9                 if(t == 1){
10                     if(brackets[j] >= 0 && brackets[j + i - 1] <= 0){//要加的括号的第一个运算数周围没有右括号,且 最后一个运算数周围没有左括号
11                         int counteract = 0;
12                         for(int k = j;k < j + i;k++){//将要加的括号之间的所有运算数对应的brackets相加,
13                                                         //如果和为0说明这个括号之间的括号是匹配的,不会出现括号交叉现象
14                             counteract += brackets[k];
15                         }
16                         if(counteract == 0){
17                             brackets[j]++;
18                             brackets[j + i - 1]--;
19                         }
20                     }
21                 }
22             }
23         }
24         return brackets;
25     }
26     

 

上面方法有bug,修改版为:

    // 随机生成括号,参数为运算式的运算数的个数
    private static int[] randomAddBracket(int length) throws MyException {
        if(length <= 1)
        {
            throw new MyException("运算式长度不能小于2");
        }
        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 counteract1 = 0,counteract2 = 0,counteract3 = 0;
                        for (int k = j; k < j + i; k++) {// 将要加的括号之间的所有运算数对应的brackets相加,
                                                            // 如果和为0说明这个括号之间的括号是匹配的,不会出现括号交叉现象
                            counteract1 += brackets[k];
                        }
                        for (int k = 0; k < j - 1; k++) {// 将要加的括号之前的所有运算数对应的brackets相加,
                            // 如果和为0说明这个括号之间的括号是匹配的,不会出现括号交叉现象
                            counteract2 += brackets[k];
                        }
                        for (int k = j + i; k < length; k++) {// 将要加的括号之后的所有运算数对应的brackets相加,
                            // 如果和为0说明这个括号之间的括号是匹配的,不会出现括号交叉现象
                            counteract3 += brackets[k];
                        }
                        
                        if (counteract1 == 0 && counteract2 == 0 && counteract3 == 0) {
                            brackets[j]++;
                            brackets[j + i - 1]--;
                            j += i;
                        }
                    }
                }
            }
        }
        return brackets;
    }

 

 

 

表达式计算:利用堆栈将中缀表达式转换为后缀表达式进行运算

代码为:

 1 //表达式计算,参数为字符串类型的运算式
 2     public static String expressCalculate(String express,int hasFuShu,int hasYuShu,int type,int symbolNum){
 3         Stack<String> num = new Stack<String>();
 4         Stack<String> symbolS = new Stack<String>();
 5         symbolS.push("#");
 6         express += "#";
 7         char ch;
 8         int i = 0;
 9         int s = 0;
10         ch = express.charAt(i);
11         while(s < symbolNum){
12             if(ch == ' '){//读到空格,说明开始读运算数
13                 String readNumStr = "";
14                 while(true){
15                     ch = express.charAt(++i);
16                     if(ch == ' '){
17                         break;
18                     }
19                     readNumStr += ch;
20                     
21                 }
22                 if((i + 1) < express.length()){
23                     ch = express.charAt(++i);
24                 }
25                 num.push(readNumStr);
26             }else{//读到的是运算符
27                 char compare = priorityCompare(symbolS.peek(),ch + "");
28                 
29                 if(compare == '='){//如果是右括号
30                     symbolS.pop();
31                     ch = express.charAt(++i);
32                 }else if(compare == '>'){//ch的优先级小于栈顶的优先级     比栈顶的优先级高就不算,入栈,低就弹栈运算
33                     //弹出两个运算数,弹出一个运算符
34                     String bStr = num.pop();
35                     String aStr = num.pop();
36                     String symbolT = symbolS.pop();
37                     String c = yunSuan(aStr,bStr,symbolT,hasFuShu,hasYuShu,type);
38                     if(c.equals("ERROR")){
39                         return "ERROR";
40                     }else if(c.indexOf("余") >= 0 && s != symbolNum - 1){//有余数
41                         return "ERROR";
42                     }else{
43                         num.push(c);
44                     }
45                     s++;
46                 }else{
47                     symbolS.push(ch + "");
48                     if((i + 1) < express.length()){
49                         ch = express.charAt(++i);
50                     }
51                 }
52             
53             }
54         }
55         return num.pop();
56     }

 

 

程序全部代码为

 

  1 package test;
  2 
  3 /*
  4  * 是否有乘除法
  5  * 括号
  6  * 数值范围
  7  * 加减有无负数
  8  * 除法余数
  9  */
 10 
 11 import java.util.Random;
 12 import java.util.Scanner;
 13 import java.util.Stack;
 14 
 15 
 16 
 17 public class SiZe {
 18 
 19     public static void main(String[] args) {
 20         // TODO Auto-generated method stub
 21         Scanner scan = new Scanner(System.in);
 22         System.out.println("0、整数式   1、分数式");
 23         int type = scan.nextInt();
 24         System.out.println("生成的运算式个数:");
 25         int n = scan.nextInt();
 26         System.out.println("是否有乘除法(1有,0没有)");
 27         int hasChengChu = scan.nextInt();
 28         System.out.println("是否有括号(1有,0没有)");
 29         int hasKuoHao = scan.nextInt();
 30         System.out.println("加减有无负数(1有,0没有)");
 31         int hasFuShu = scan.nextInt();
 32         System.out.println("除法有无余数(1有,0没有)");
 33         int hasYuShu = scan.nextInt();
 34         System.out.println("数值范围(最大数)");
 35         int maxNum = scan.nextInt();
 36         String[] yunSuanShiArray = createYunSuanShi(hasChengChu, hasKuoHao, hasFuShu, hasYuShu, maxNum, n, type);
 37         for(int i = 0;i < yunSuanShiArray.length;i++){
 38             System.out.println(yunSuanShiArray[i]);
 39         }
 40         scan.close();
 41     }
 42     
 43     
 44     //生成整数计算式添加限制条件,type为运算式类型  0代表整数式,1代表真分数式
 45     public static String[] createYunSuanShi(int hasChengChu,int hasKuoHao,int hasFuShu,int hasYuShu,int maxNum,int n,int type) {
 46         int i = 0;
 47         String yunSuanShiTemp;
 48         String[] yunSuanShiArray = new String[n];
 49         int operatorScope = 2 + 2 * hasChengChu;//运算符范围,2或4,2代表只有加减,4代表有加减乘除
 50         int length;
 51         String[] operatorArray = {"+","-","*","/"};
 52         String[] operatorNum = null;//存储运算数
 53         int num_index;//运算数下标
 54         String[] operatorSymbol = null;//存储运算符
 55         int symbol_index;//运算符下标
 56         int[] brackets = null;//存储括号个数
 57         
 58         while(i < n) {
 59             length = Integer.parseInt(getOperatorNumber(0, 9)) + 2;//计算式运算数长度
 60             operatorNum = new String[length];
 61             operatorSymbol = new String[length - 1];
 62             num_index = 0;
 63             symbol_index = 0;
 64             operatorNum[num_index++] = getOperatorNumber(type, maxNum);//随机生成操作数
 65             for(int j = 0;j < length - 1;j++){
 66                 operatorSymbol[symbol_index++] = operatorArray[Integer.parseInt(getOperatorNumber(0, operatorScope))];//随机生成操作符
 67                 operatorNum[num_index++] = getOperatorNumber(type, maxNum);//随机生成操作数
 68             }        
 69             if(hasKuoHao == 1){
 70                 brackets = randomAddBracket(length);//生成括号数组
 71             }
 72             //构造运算式
 73             yunSuanShiTemp = "";
 74             for(int j = 0;j < length;j++){
 75                 //添加左括号
 76                 if(hasKuoHao == 1){
 77                     for(int k = 0;k < brackets[j];k++){
 78                         yunSuanShiTemp += "(";
 79                     }
 80                 }
 81                 yunSuanShiTemp += " " + operatorNum[j] + " ";//加上运算数
 82                 
 83                 //添加右括号
 84                 if(hasKuoHao == 1){
 85                     for(int k = 0;k > brackets[j];k--){
 86                         yunSuanShiTemp += ")";
 87                     }
 88                 }
 89                 //如果不是最后一个运算数则要加上运算符
 90                 if(j != length - 1){
 91                     yunSuanShiTemp += operatorSymbol[j];
 92                 }
 93             }
 94             
 95             //计算结果
 96             String answer = expressCalculate(yunSuanShiTemp, hasFuShu, hasYuShu, type, length - 1);
 97             if((answer.equals("ERROR"))){
 98                 continue;
 99             }
100             yunSuanShiTemp += "=" + answer;
101             //检验重复
102             boolean chongFu = false;
103             for(int j = 0;j < i;j++){
104                 if((yunSuanShiArray[j].equals(yunSuanShiTemp))){
105                     chongFu = true;
106                     break;
107                 }
108             }
109             if(chongFu == false){
110                 yunSuanShiArray[i++] = yunSuanShiTemp;
111             }
112         }
113         return yunSuanShiArray;
114     }
115     
116     //表达式计算,参数为字符串类型的运算式
117     public static String expressCalculate(String express,int hasFuShu,int hasYuShu,int type,int symbolNum){
118         Stack<String> num = new Stack<String>();
119         Stack<String> symbolS = new Stack<String>();
120         symbolS.push("#");
121         express += "#";
122         char ch;
123         int i = 0;
124         int s = 0;
125         ch = express.charAt(i);
126         while(s < symbolNum){
127             if(ch == ' '){//读到空格,说明开始读运算数
128                 String readNumStr = "";
129                 while(true){
130                     ch = express.charAt(++i);
131                     if(ch == ' '){
132                         break;
133                     }
134                     readNumStr += ch;
135                     
136                 }
137                 if((i + 1) < express.length()){
138                     ch = express.charAt(++i);
139                 }
140                 num.push(readNumStr);
141             }else{//读到的是运算符
142                 char compare = priorityCompare(symbolS.peek(),ch + "");
143                 
144                 if(compare == '='){//如果是右括号
145                     symbolS.pop();
146                     ch = express.charAt(++i);
147                 }else if(compare == '>'){//ch的优先级小于栈顶的优先级     比栈顶的优先级高就不算,入栈,低就弹栈运算
148                     //弹出两个运算数,弹出一个运算符
149                     String bStr = num.pop();
150                     String aStr = num.pop();
151                     String symbolT = symbolS.pop();
152                     String c = yunSuan(aStr,bStr,symbolT,hasFuShu,hasYuShu,type);
153                     if(c.equals("ERROR")){
154                         return "ERROR";
155                     }else if(c.indexOf("余") >= 0 && s != symbolNum - 1){//有余数
156                         return "ERROR";
157                     }else{
158                         num.push(c);
159                     }
160                     s++;
161                 }else{
162                     symbolS.push(ch + "");
163                     if((i + 1) < express.length()){
164                         ch = express.charAt(++i);
165                     }
166                 }
167             
168             }
169         }
170         return num.pop();
171     }
172     
173     public static String yunSuan(String aStr,String bStr,String symbol,int hasFuShu,int hasYuShu,int type){
174         if(type == 0){//整数
175             int a = Integer.parseInt(aStr);
176             int b = Integer.parseInt(bStr);
177             if(symbol.equals("+")){
178                 return "" + (a + b);
179             }else if(symbol.equals("-")){
180                 if(a - b < 0 && hasFuShu == 0){
181                     return "ERROR";
182                 }else{
183                     return "" + (a - b);
184                 }
185             }else if(symbol.equals("*")){
186                 return "" + (a * b);
187             }else{
188                 if(b == 0){
189                     return "ERROR";
190                 }
191                 if(a % b == 0){
192                     return "" + (a / b);
193                 }else{
194                     if(hasYuShu == 1){
195                         return (a / b) + "余" + (a % b);
196                     }else{
197                         return "ERROR";
198                     }
199                 }
200             }
201         }else{//分数
202             String[] af = aStr.split("/");
203             String[] bf = bStr.split("/");
204             if(af[0].equals("0") || bf[0].equals("0")){
205                 return "ERROR";
206             }
207             FenShu a = new FenShu(Integer.parseInt(af[1]),Integer.parseInt(af[0]));
208             FenShu b = new FenShu(Integer.parseInt(bf[1]),Integer.parseInt(bf[0]));
209             if(symbol.equals("+")){
210                 return a.add(b).toString();
211             }else if(symbol.equals("-")){
212                 FenShu c = a.subtract(b);
213                 if(hasFuShu == 1 && c.getNumerator() < 0){
214                     return "ERROR";
215                 }
216                 return c.toString();
217             }else if(symbol.equals("*")){
218                 return a.multiply(b).toString();
219             }else{
220                 return a.divide(b).toString();
221             }
222         }
223     }    
224     //判断优先级
225     public static char priorityCompare(String a,String b){
226         char[][] priority = {
227                 {'>','>','<','<','<','>','>'},
228                 {'>','>','<','<','<','>','>'},
229                 {'>','>','>','>','<','>','>'},
230                 {'>','>','>','>','<','>','>'},
231                 {'<','<','<','<','<','=','>'},
232                 {'>','>','>','>',' ','>','>'},
233                 {'<','<','<','<','<',' ','='}
234         };
235         int a_index = index_symbol(a);
236         int b_index = index_symbol(b);
237         return priority[a_index][b_index];
238     }
239     
240     public static int index_symbol(String a){
241         String p = "+-*/()#";
242         return p.indexOf(a);
243     }
244     
245     //随机生成括号,参数为运算式的运算数的个数
246     public static int[] randomAddBracket(int length){
247         int[] brackets = new int[length];
248         for(int i = 0;i < brackets.length;i++)   brackets[i] = 0;
249         Random rd = new Random();
250         for(int i = 2;i < length;i++){//添加的括号长度(括号包围的运算数的个数)
251             for(int j = 0;j < length - i + 1;j++){
252                 int t = rd.nextInt(2);//随机生成0或1,0代表不加括号,1代表加括号
253                 if(t == 1){
254                     if(brackets[j] >= 0 && brackets[j + i - 1] <= 0){//要加的括号的第一个运算数周围没有右括号,且 最后一个运算数周围没有左括号
255                         int counteract = 0;
256                         for(int k = j;k < j + i;k++){//将要加的括号之间的所有运算数对应的brackets相加,
257                                                         //如果和为0说明这个括号之间的括号是匹配的,不会出现括号交叉现象
258                             counteract += brackets[k];
259                         }
260                         if(counteract == 0){
261                             brackets[j]++;
262                             brackets[j + i - 1]--;
263                         }
264                     }
265                 }
266             }
267         }
268         return brackets;
269     }
270     
271     //随机生成一个运算数(                type==0代表生成整数,type==1代表生成真分数,maxNum代表数值范围 0-(maxNum-1)               )
272     public static String getOperatorNumber(int type,int maxNum){
273         Random rd = new Random();
274         int a;
275         while(true){
276             a = rd.nextInt(maxNum);
277             if(type == 0){//随机生成一个整数
278                 return "" + a;
279             }else{//随机生成一个真分数
280                 if(a == 0){
281                     continue;
282                 }
283                 int b = rd.nextInt(a);
284                 FenShu c = new FenShu(a,b);
285                 return c.toString();
286             }
287         }
288     }
289     
290 
291 
292 }
View Code

 

 

 

 

 

FenShu类

  1 package test;
  2 
  3 public class FenShu {
  4     private int denominator,numerator;
  5 
  6     public int getDenominator() {
  7         return denominator;
  8     }
  9 
 10     public void setDenominator(int denominator) {
 11         this.denominator = denominator;
 12     }
 13 
 14     public int getNumerator() {
 15         return numerator;
 16     }
 17 
 18     public void setNumerator(int numerator) {
 19         this.numerator = numerator;
 20     }
 21 
 22     public FenShu(int denominator, int numerator) {
 23         this.denominator = denominator;
 24         this.numerator = numerator;
 25         yueJian();
 26     }
 27     
 28     FenShu(){}
 29     
 30     //约简
 31     public void yueJian(){
 32         int y = 1;
 33         for(int i = numerator;i > 1;i--){
 34             if(numerator % i == 0 && denominator % i == 0){
 35                 y = i;
 36                 break;
 37             }
 38         }
 39 //        int nc = numerator,dc = denominator;
 40 //        if(nc != 0){
 41 //            while(nc != dc - nc){
 42 //                y = dc - nc;
 43 //                if(nc > y){
 44 //                    dc = nc;
 45 //                    nc = y;
 46 //                }else{
 47 //                    dc = y;
 48 //                }
 49 //            }
 50 //            y = nc;
 51 //    
 52             numerator /= y;
 53             denominator /= y;
 54         
 55     }
 56     
 57     //
 58     public FenShu add(FenShu b){
 59         FenShu c = null;
 60         int nNumerator = this.numerator * b.getDenominator() + this.denominator * b.getNumerator();
 61         int nDenominator = this.denominator * b.getDenominator();
 62         c = new FenShu(nDenominator,nNumerator);
 63         return c;
 64     }
 65     
 66     //
 67     public FenShu subtract(FenShu b){
 68         FenShu c = null;
 69         int nNumerator = this.numerator * b.getDenominator() - this.denominator * b.getNumerator();
 70         int nDenominator = this.denominator * b.getDenominator();
 71         c = new FenShu(nDenominator,nNumerator);
 72         return c;
 73     }
 74     
 75     //
 76     public FenShu multiply(FenShu b){
 77         FenShu c = null;
 78         int nNumerator = this.numerator * b.getNumerator();
 79         int nDenominator = this.denominator * b.getDenominator();
 80         c = new FenShu(nDenominator,nNumerator);
 81         return c;
 82     }
 83     
 84     //
 85     public FenShu divide(FenShu b){
 86         FenShu c = null;
 87         int nNumerator = this.numerator * b.getDenominator();
 88         int nDenominator = this.denominator * b.getNumerator();
 89         c = new FenShu(nDenominator,nNumerator);
 90         return c;
 91     }
 92     
 93     //输出分数形式
 94     public String toString(){
 95         if(numerator != 0){
 96 //            if(numerator % denominator == 0)
 97 //                return "" + numerator / denominator;
 98             return numerator + "/" + denominator;
 99         }
100         return "0";
101     }
102     
103 }
View Code

 

 

 

运行结果截图:

 

 

 

 

 

 

 

PSP0级过程文档

项目计划总结:

 

 

时间记录日志

 

缺陷记录日志

 

posted @ 2017-03-10 14:54  liuxining  阅读(264)  评论(0编辑  收藏  举报