zoukankan      html  css  js  c++  java
  • 软件工程概论作业二

    题目:

    设计思想:

    生成运算式:用随机数产生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级过程文档

    项目计划总结:

    时间记录日志

    缺陷记录日志

  • 相关阅读:
    【Leetcode】【Easy】Remove Duplicates from Sorted List
    【Leetcode】【Easy】Pascal's Triangle II
    【Leetcode】【Easy】Pascal's Triangle
    【Leetcode】【Easy】Binary Tree Level Order Traversal II
    【Leetcode】【Easy】Binary Tree Level Order Traversal
    【Leetcode】【Easy】Maximum Depth of Binary Tree
    【Leetcode】【Easy】Minimum Depth of Binary Tree
    【Leetcode】【Easy】Balanced Binary Tree
    【Leetcode】【Easy】Symmetric Tree
    如何使用Action.Invoke()触发一个Storyboard
  • 原文地址:https://www.cnblogs.com/liuxining/p/6530730.html
Copyright © 2011-2022 走看看