• 软件工程概论作业二


    题目:

    设计思想:

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

    项目计划总结:

    时间记录日志

    缺陷记录日志

  • 相关阅读:
    SharePoint 在文本编辑框中插入图片报错
    SharePoint 修改列表阀值
    SharePoint 获取SPListItem附件地址
    SharePoint 验证用户组是否存在当前用户方法
    SharePoint中查看用户登录IP与用户名
    SharePoint CAML中通过ID查找Lookup字段
    SharePoint 服务器修改密码(前端服务器与数据库服务器分开)
    20191128-1 总结
    康哲 20191121-1 每周例行报告
    对成员的感谢
  • 原文地址:https://www.cnblogs.com/liuxining/p/6530730.html
Copyright © 2020-2023  润新知