个人作业1——四则运算题目生成程序

本文介绍了一款能够生成包含分数的四则运算题目的软件。该软件可根据用户设定的数字范围及题目数量,随机生成不重复的运算题目,并支持后缀表达式转换与答案验证等功能。

一、题目描述

1.随机生成指定数量的不重复的四则运算表达式
2.表达式的数字范围也可指定
3.将生成的题目输出到文件上
4.用户可回答问题,程序可查错
5.支持分数运算,答案也为分数

二、需求分析

用户选择生成题目后随机生成不重复的四则运算表达式并写入文件
用户填写答案到相应文件后选择检查答案可得到对错题目
四则运算支持分数答案

三、功能设计

1.用户选择功能 生成题目 提交题目 推出
2.选择生成题目后要求用户输入数字范围和题目数量
3.生成相应数量和数字范围的表达式并写入文件
4.用户在文件中答题后选择提交答案
5.程序返回答题的正确数目和错误数目。

四、代码说明

1.Num类
   题目中所有的数都有Num类来表示。
   Num类由分子和分母两个属性组成。
   重写该类的toString方法,使其在输出时能根据情况输出为整数和分数。
   其中,若表示的数为真分数时,需要对其进行约分,所以添加一个reduction方法进行约分
   约分需要用到最大公约数,所以写一个递归函数getGCD来求分子分母的最大公约数,其中用到了辗转相除法。
   在Num类中添加了一个静态方法count,用来进行Num对象之间的计算。
   还添加了一个判断Num大小的静态方法max
   最后添加了一个方法createNum,能随机生成Num
   public String toString() {
    if (this.denomenator == 1) {
        return String.valueOf(this.numerator);
    } else if (this.numerator > this.denomenator) {
        if (this.numerator % this.denomenator == 0) {
            return String.valueOf(this.numerator / this.denomenator);
        } else {
            return this.numerator / this.denomenator + "'" + this.numerator % this.denomenator + "/"
                    + this.denomenator;
        }
    } else if (this.numerator < this.denomenator) {
        return this.numerator + "/" + this.denomenator;
    } else if (this.numerator == 0) {
        return "0";
    }
    return "1";
}
2.Expression类
   该类用来生成四则运算表达式,并对表达式进行后缀转换。
   表达式用Arraylist来存储
   添加createExpression方法用于表达式生成,原理为根据输入的运算发数目进行循环,每次循环生成一个Num和一个运算符存入数组,并随机添加括号,最后删除多余的运算符
   添加toPRN方法用于将表达式转换为后缀表达式,原理为每次读到数字时放入数组中,读到符号时进栈,直到读到下个符号时判断优先级,若前一个优先级高,则出栈进数组,否则继续将新的符号进栈。若读到括号,则将括号后的所有符号进栈,直到读到“)”时,将“(”后的所有符号出栈。
   其中isOperator用于判断是否为运算符,priority判断符号优先级,randomOperator用于生成随机运算符,toString用于将Arraylist转换为String。
   public ArrayList<Object> createExpression(int operator_no, int edge) {
    ArrayList<Object> expression = new ArrayList<Object>();
    Random r = new Random();
    int backet = 0;
    int backet_no = 0;
    for (int i = 1; i <= operator_no + 1; i++) {
        backet = r.nextInt(3);
        if (backet_no != 0 && backet != 0 && expression.get(expression.size() - 1) != "(") {
            Num num = new Num();
            num.randomNum(edge);
            expression.add(num);
            expression.add(")");
            expression.add(randomOperator());
            backet_no--;
        } 
        else if (i != operator_no + 1) {
            if (backet == 1) {
                expression.add(0, "(");
                ++backet_no;
                Num num = new Num();
                num.randomNum(edge);
                expression.add(num);
                expression.add(randomOperator());
            } else if (backet == 2) {
                Num num = new Num();
                expression.add("(");
                ++backet_no;
                num.randomNum(edge);
                expression.add(num);
                expression.add(randomOperator());
            } else {
                Num num = new Num();
                num.randomNum(edge);
                expression.add(num);
                expression.add(randomOperator());
            }
        } else {
            Num num = new Num();
            num.randomNum(edge);
            expression.add(num);
            expression.add(randomOperator());
        }
    }
    expression.remove(expression.size() - 1);
    while (backet_no != 0) {
        expression.add(")");
        backet_no--;
    }
    while (expression.get(0) == "(") {
        backet = 0;
        int bracket_leng = 0;
        String o = "";
        for (int j = 0; j < expression.size(); j++) {
            o = expression.get(j).toString();
            if (o == "(") {
                backet++;
                bracket_leng--;
            }
            if (o == ")") {
                backet--;
                bracket_leng--;
            }
            if (backet == 0 && bracket_leng != (2 * operator_no)) {
                return expression;
            }
            if (backet >= 1) {
                bracket_leng++;
            }
        }
        if (bracket_leng == (2 * operator_no)) {
            expression.remove(0);
            expression.remove(expression.size() - 1);
        }
    }
    return expression;
}
3.NumTree类
   该类用于将后缀表达式存入二叉树中,有left,right,value,data四个属性,left存储左节点,right存储右节点,value存储该树的运算过后的结果,data为存储的值
   createNumTree方法用于将后缀表达式建立为一个树,原理为每次读到Num类是将其建立为节点,并入栈;读到运算符时,将其建立为节点并将栈中的两个节点出栈,根据value判断大小,大的为左节点,小的为右节点,然后入栈。直到读入最后一个运算符时建树,返回建立的树。
   max方法为判断两个树节点的大小,toString借用递归方法outPutTree将树转换为字符串。outPutTree用后序遍历的递归方法将树转换为字符串。
   public NumTree createTree(ArrayList<Object> rpn) {
    Stack<Object> stack = new Stack<Object>();
    NumTree t = null;
    Object ob;
    for (int i = 0; i < rpn.size(); i++) {
        t = new NumTree();
        ob = rpn.get(i);
        if (Expression.isOperator(ob.toString())) {
            NumTree t2 = (NumTree) stack.pop();
            NumTree t1 = (NumTree) stack.pop();
            
                if (NumTree.max(t1, t2)) {
                    t.setData(ob.toString());
                    t.setLeft(t1);
                    t.setRight(t2);
                    t.setValue(Num.count(t1.getValue(), t2.getValue(), ob.toString()));
                    if (t1.getValue().getDenomenator() == 0) {
                        return new NumTree("0", t.getValue(),null, null );
                    }
                } else {
                    t.setData(ob.toString());
                    t.setLeft(t2);
                    t.setRight(t1);
                    t.setValue(Num.count(t1.getValue(), t2.getValue(),ob.toString()));
                    if (t.getValue().getDenomenator() == 0) {
                        return new NumTree("0", t.getValue(), null, null);
                    }
                }
                stack.push(t);
            
        } else {
            t.setData(ob.toString());
            t.setValue((Num) ob);
            stack.push(t);
        }
    }
    return t;
}
4.check类
   用于在生成表达式时的查重,检查文件是否已存在和表达式答案是否符合格式
5.Main类
   与用户进行交互的类,负责各个类的调用和输出内容到文件

五、代码

码云地址
https://gitee.com/fandre/arithmetic.git

六、测试

977168-20180331144554277-616387282.png
977168-20180331145550408-511287325.png
977168-20180331145714418-1817993286.png
977168-20180331145757015-1392782495.png

七、psp表

977168-20180331112429168-2142364092.png

转载于:https://www.cnblogs.com/fandre/p/8681447.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值