• 软件工程概论个人作业03


    这次上课,老师对四则运算的程序又做了一些系统的要求。

    一、要求

    1.定义:
      自然数:0, 1, 2, …。
      真分数:1/2, 1/3, 2/3, 1/4, 1’1/2, …。
      运算符:+, −, ×, ÷。
      括号:(, )。
      等号:=。
      分隔符:空格(用于四则运算符和等号前后)。
    2.算术表达式:
      e := n | e1 + e2 | e1 − e2 | e1 × e2 | e1 ÷ e2 | (e),
      其中e, e1和e2为表达式,n为自然数或真分数。
      四则运算题目:e = ,其中e为算术表达式。
    3.定义参数控制生成题目的个数。
      例如,参数n=10;则将生成10个题目。
    4.定义参数控制题目中数值(自然数、真分数和真分数分母)的范围。
      例如参数r= 10,将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。
      该参数必须给定,否则程序报错并给出帮助信息。
    5.生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1 − e2的子表达式,那么e1 ≥ e2。
    6.生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。
    7.每道题目中出现的运算符个数不超过3个。
    8.程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目
      例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。3+(2+1)和1+2+3这两个题目是重复的,由于+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目
    9.生成的题目存储到数据库中,格式如下:
      1. 四则运算题目1
      2. 四则运算题目2
      ……
      其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。
    10.在生成题目的同时,计算出所有题目的答案,并存入数据库文件。格式如下:
      1. 答案1
      2. 答案2
        特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。
    11.程序应能支持一万道题目的生成。
    12.程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,
      统计结果输出到数据表文件Grade,格式如下:
      Correct: 5 (1, 3, 5, 7, 9)
      Wrong: 5 (2, 4, 6, 8, 10)
      其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。
    二、编程思路

         (1)查重

          每三个元素划分为一组,来进行子表达式之间的查重,进行判断是否相同。

      (2)数据库连接、释放  

           获取数据库连接的方法是将注册数据库驱动,获得一个数据库的连接进行封装,返回一个数据库连接对象;另外,释放资源的方法是将释放查询数据库结果集对象、数据库操作对象和数据库连接对象进行封装。

    三、源代码:

    package hh;
    
    import java.util.Random;
    import java.util.Scanner;
    import java.util.Stack;
    
    //分数类
    class fraction {
        public int fenMu,fenZi;
    
        public int getFenMu() {
            return fenMu;
        }
    
        public void setFenMu(int fenMu) {
            this.fenMu = fenMu;
        }
    
        public int getFenZi() {
            return fenZi;
        }
    
        public void setFenZi(int fenZi) {
            this.fenZi = fenZi;
        }
    
        public fraction(int fenMu, int fenZi) {
            this.fenMu = fenMu;
            this.fenZi = fenZi;
            yueFen();
        }
        
        public fraction(){}
        
      //找出两数的最大公约数
        public int MaxCommon(int a,int b){
        	//保证第一个参数大于第二个参数
            if(a<b)
            {
                int temp;
                temp=a;
                a=b;
                b=temp;
            }
            while(a%b!=0)   //在余数不为零时循环
            {
                int temp=a%b;
                a=b;
                b=temp;
            }
            return b;  //返回最大公约数
        }
        
        //找出两数的最小公倍数
        public int MinCommon(int a,int b){
        	return a*b/MaxCommon(a,b);
        }
        
        //约分化简
        public void yueFen(){
            int y = 1;
            for(int i = fenZi;i > 1;i--){
                if(fenZi % i == 0 && fenMu % i == 0){
                    y = i;
                    break;
                }
            }
                fenZi /= y;
                fenMu /= y;
            
        }
        
        //计算(加)
        public fraction add(fraction b){
        	fraction c = null;
            int newFenZi = this.fenZi * b.getFenMu() + this.fenMu * b.getFenMu();
            int newFenMu = this.fenMu * b.getFenMu();
            c = new fraction(newFenMu,newFenZi);
            return c;
        }
        
        //计算(减)
        public fraction subtract(fraction b){
        	fraction c = null;
            int newFenZi = this.fenZi * b.getFenMu() - this.fenMu * b.getFenZi();
            int newFenMu = this.fenMu * b.getFenMu();
            c = new fraction(newFenMu,newFenZi);
            return c;
        }
        
        //计算(乘)
        public fraction multiply(fraction b){
        	fraction c = null;
            int newFenZi = this.fenZi * b.getFenZi();
            int newFenMu = this.fenMu * b.getFenMu();
            c = new fraction(newFenMu,newFenZi);
            return c;
        }
        
        //计算(除)
        public fraction divide(fraction b){
        	fraction c = null;
            int newFenZi = this.fenZi * b.getFenMu();
            int newFenMu = this.fenMu * b.getFenZi();
            c = new fraction(newFenMu,newFenZi);
            return c;
        }
        
        //输出分数形式
        public String toString(){
            if(fenZi != 0){
                return fenZi + "/" + fenMu;
            }
            return "0";
        }
        
    }
    
    public class kk {
    	public static String[] Answer=new String[100];
    	//生成整数计算式添加限制条件,type为运算式类型  0代表整数式,1代表真分数式
        public static String[] createYunSuanShi(int hasChengChu,int hasKuoHao,int hasFuShu,int hasYuShu,int minNum,int maxNum,int n,int type) {
            int i = 0;
            int z = 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, 0,9)) + 2;//计算式运算数长度
                operatorNum = new String[length];
                operatorSymbol = new String[length - 1];
                num_index = 0;
                symbol_index = 0;
                operatorNum[num_index++] = getOperatorNumber(type,minNum, maxNum);//随机生成操作数
                for(int j = 0;j < length - 1;j++){
                    operatorSymbol[symbol_index++] = operatorArray[Integer.parseInt(getOperatorNumber(0,0,operatorScope-1))];//随机生成操作符
                    operatorNum[num_index++] = getOperatorNumber(type, minNum,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*/;
                Answer[z]=answer;
                z++;
                //检验重复
                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";
                }
                fraction a = new fraction(Integer.parseInt(af[1]),Integer.parseInt(af[0]));
                fraction b = new fraction(Integer.parseInt(bf[1]),Integer.parseInt(bf[0]));
                if(symbol.equals("+")){
                    return a.add(b).toString();
                }else if(symbol.equals("-")){
                	fraction c = a.subtract(b);
                    if(hasFuShu == 1 && c.getFenZi() < 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 minNum,int maxNum){
            Random rd = new Random();
            int a,b;
            while(true){
                a = rd.nextInt(maxNum-minNum+1)+minNum;
                if(type == 0){//随机生成一个整数
                    return "" + a;
                }else{//随机生成一个真分数
                    if(a == 0){
                        continue;
                    }
                    b = rd.nextInt(maxNum-minNum+1)+minNum;
                    System.out.println(b);
                    while(b>=a)
                    {
                    	b = rd.nextInt(maxNum-minNum+1)+minNum;
                    	if(a>b)
                    	{
                    		break;
                    	}
                    }
                    System.out.println(b);
                    fraction c = new fraction(a,b);
                    return c.toString();
                }
            }
        }
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Scanner sc = new Scanner(System.in);
    		System.out.print("请输入所要生成题目的数目:");
    	    int n = sc.nextInt();
            System.out.print("请输入: 0、整数式 ; 1、分数式:");
            int type = sc.nextInt();
            System.out.print("是否有乘除法?(1有,0没有):");
            int hasChengChu = sc.nextInt();
            System.out.print("是否有括号?(1有,0没有):");
            int hasKuoHao = sc.nextInt();
            System.out.print("加减有无负数?(1有,0没有):");
            int hasFuShu = sc.nextInt();
            System.out.print("除法有无余数?(1有,0没有):");
            int hasYuShu = sc.nextInt();
            System.out.print("数值范围(最小数):");
            int minNum = sc.nextInt();
            System.out.print("数值范围(最大数):");
            int maxNum = sc.nextInt();
            String[] yunSuanShiArray = createYunSuanShi(hasChengChu, hasKuoHao, hasFuShu, hasYuShu,minNum, maxNum, n, type);
            for(int i = 0;i < yunSuanShiArray.length;i++){
                System.out.print(yunSuanShiArray[i]);
                String result=sc.next();
                if(result.equals(Answer[i])){
                	System.out.print(" 回答正确!");
                }
                else{
                	System.out.print(" 回答错误!"+"正确答案为:"+Answer[i]);
                }
                System.out.println();
            }
            sc.close();
    	}
    }
    

    四、截图

    五、反思:

    下星期的编程任务应该是改为web版,这一星期的编程时间并不是特别长,所以下个星期应该更加努力去完善程序,争取早日完成这个程序!

        

  • 相关阅读:
    AndroidManifest.xml文件详解(activity)(二)
    Android Studio显示可视化编辑界面
    Delphi XE2 新增 System.Zip 单元,压缩和解压缩文件
    LockBox的安装
    Kernel的意义
    Mathematical optimization数学上的最优化
    矩阵分析
    【2008nmj】支持向量机
    【2008nmj】BP二元分类
    【2008nmj】Logistic回归二元分类感知器算法.docx
  • 原文地址:https://www.cnblogs.com/zhangjiabei/p/6562105.html
Copyright © 2020-2023  润新知