结对项目

四则运算

软工作业 结对编程
作业要求 作业
Github Github
作业题目 四则运算

姓名 学号
徐潮松 3118005387
丘美珠 3218005399

PSP表格

PSP2.1 Pair-programming Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60 100
Estimate 估计这个任务需要多少时间 300 500
Development 开发 600 1200
Analysis 需求分析(包括学习新技术) 120 150
Design Spec 生成设计文档 60 80
Design Review 设计复审 20 30
Coding Standard 代码规范(为目前的开发制定合适的规范) 10 20
Design 具体设计 50 80
Coding 具体编码 400 600
Code Review 代码复审 30 60
Test 测试(自我测试,修改代码,提交修改) 60 90
Reporting 报告 30 50
Test Report 测试报告 60 120
Size Measurement 计算工作量 60 50
Postmortem&Process Improvement Plan 事后总结,并提出过程改进计划 30 40
合计 1890 3170

一、效能分析

类图

内存消耗

CPU Load

二、设计实现过程

2.1 数据结构

使用二叉树存放四则运算式,比如1+2×3÷(4-5)+6这个表达式就可以使用以下二叉树表示,中序遍历二叉树时就可以还原四则运算。

作业要求四则运算式中不能出现负数,(4-5)在二叉树中调换位置即可。

2.2 实现步骤

实现步骤

流程图

在主函数main()中输入-n-r两个参数, 传入并执行generateMap()函数,在generateMap() 中用for循环new ArithmeticTree对象,在ArithmeticTree的构造器中,计算了四则运算结果,返回一个OperatorNode结点,在generateMap()函数调用ArithmeticTree对象中的值,包括计算出的结果,调用hashMap.put()保存在HashMap对象中,再传入writFile()写出文件。

三、代码说明

功能
Main 主函数,获取输入值,计算结果
ArithmeticTree 构建四则运算的二叉树
FractionOperation 分数的四则运算操作
DataNode 存放数据的结点
OperatorNode 存放操作符的结点
FileUtils IO流操作,文件输入输出
GenerateUtils 随机生成四则运算
   /**
     * 获取随机范围内的随机整数
     * @param range 范围
     * @return 随机数
     */
    public static int getRandomInRange(int range) {
        ThreadLocalRandom random = ThreadLocalRandom.current();
        return random.nextInt(range);
    }
 /**
     * 构建生成四则运算表达式的二叉树
     * @param number 运算符数量
     * @return 二叉树头节点
     */
    public DataNode generateNode(int number) {
        //如果是0就构造叶子节点
        if (number == 0) {
            return new DataNode(FractionOperation.generateFraction(), null, null, 1);
        }
        //其他都是构造符号节点
        OperatorNode rootNode = new OperatorNode(null, null, OPERATORS[GenerateUtils.getRandomInRange(4)]);
        int leftNum = GenerateUtils.getRandomInRange(number);
        //递归下去构造左孩子和右孩子
        rootNode.left = generateNode(leftNum);
        //总数要减去当前已经构建出来的这一个节点
        rootNode.right = generateNode(number - 1 - leftNum);
        //计算结果
        FractionOperation result = calculate(rootNode.operator, rootNode.left.result, rootNode.right.result);
        //如果是负数,交换左右孩子
        if (result.isNegative()) {
            DataNode tmp = rootNode.left;
            rootNode.left = rootNode.right;
            rootNode.right = tmp;
        }
        rootNode.result = result;
        rootNode.high = Math.max(rootNode.left.high, rootNode.right.high) + 1;
        return rootNode;
    }
/**
 * 加法
 * @param right 右节点分数
 * @return 结果
 */
public FractionOperation add(FractionOperation right) {
    // a/b+c/d =(ad+bc)/bd
    return new FractionOperation(
            this.a * right.b + this.b * right.a,
            this.b * right.b
    );
}

/**
 * 减法
 * @param right 右节点分数
 * @return 结果
 */
public FractionOperation subtract(FractionOperation right) {
    // a/b-c/d =(ad-bc)/bd
    return new FractionOperation(
            this.a * right.b - this.b * right.a,
            this.b * right.b
    );
}

/**
 * 乘法
 * @param right 右节点分数
 * @return 结果
 */
public FractionOperation multiply(FractionOperation right) {
    // a/b * c/d = ac / bd
    return new FractionOperation(
            this.a * right.a,
            this.b * right.b
    );
}

/**
 * 除法
 * @param right 右节点分数
 * @return 结果
 */
public FractionOperation divide(FractionOperation right) {
    // a/b  /  c/d = ad / bc
    return new FractionOperation(
            this.a * right.b,
            this.b * right.a
    );
}

   /**
     * 进行两个元素的计算
     * @param operator 运算符
     * @param leftFraction  左节点分数
     * @param rightFraction 右节点分数
     * @return 运算结果
     */
    private FractionOperation calculate(String operator, FractionOperation leftFraction, FractionOperation rightFraction) {
        switch (operator) {
            case ADD:
                return leftFraction.add(rightFraction);
            case SUBTRACT:
                return leftFraction.subtract(rightFraction);
            case MULTIPLY:
                return leftFraction.multiply(rightFraction);
            //可能会出现除以0的情况,即rightFraction可能为0
            case DIVIDE:
                if (rightFraction.getA() == 0) {
                    this.isDivideForZero = true;
                    rightFraction.setA(1);
                }
                return leftFraction.divide(rightFraction);
            default:
                throw new RuntimeException("该操作符不存在");
        }
    }

四、测试运行

输入

生成文件

10000道题目

答案

五、项目小结

  • 徐潮松

    开始的时候没有头绪,跟队友一起百度浏览,最后找到了用二叉树实现,所以找到方向很关键,方向对了,对实现项目要求有很大的帮助。

  • 丘美珠

    本来看到这个题目,感觉很难,最后跟队友一起百度搜索,攻克难关,在需要团队合作的项目,沟通是很重要的。

posted on 2020-10-12 17:33  Yuki-r  阅读(164)  评论(0编辑  收藏  举报

导航