四则运算

软件工程第三周做业 —— 四则运算git

 

1. 项目要求

1.1 要求阐述

  • 生成小学四则运算题题目,结果不能为负数
  • 支持真分数的四则运算

1.2 详细要求 【易知大学

1.3 详细代码 【GitHub

2. PSP表格

PSP2.1github

Personal Software Process Stagesdom

预估耗时(分钟)性能

实际耗时(分钟)单元测试

Planning学习

计划测试

15编码

25spa

    Estimate设计

    估计这个任务须要多少时间

15

25

Development

开发

247

395

    Analysis

    需求分析 (包括学习新技术)

30

45

    Design Spec

    生成设计文档

30

30

    Design Review

    设计复审 (和同事审核设计文档)

15

10

    Coding Standard

    代码规范 (为目前的开发制定合适的规范)

12

10

    Design

    具体设计

30

35

    Coding

    具体编码

60

180

    Code Review

    代码复审

30

20

    Test

    测试(自我测试,修改代码,提交修改)

40

65

Reporting

报告

85

60

    Test Report

    测试报告

30

25

    Size Measurement

    计算工做量

30

10

    Postmortem & Process Improvement Plan

    过后总结, 并提出过程改进计划

25

25

合计

 

347

480

3. 解题思路描述

  将问题分解为两部分:第一部分生成算式,第二部分计算算式的值。

3.1 第一部分

  生成算式分为三个小步骤。

  首先,使用随机数生成操做数与运算符,经过参数设置操做数与运算符的数量,再将其拼接为算式,如3×7+9÷3。

  其次,在算式上插入括号,括号插在有乘除附近的加减子算式中,如3×(7+9)÷3。

  最后,在算式的基础上将其中的数字替换为分数,若是不想使用分数则跳过此步骤。

3.2 第二部分

  计算算式的值,将算式转为逆波兰式,以后使用栈计算算式结果,结果保留分数形式,如7/2。

4. 设计实现过程

4.1 参数说明

  建立OPT方法存储相关参数,如操做数数值上限、操做数个数、使用的运算符种类、是否包含分数。

4.2 生成算式

  使用GeneralFormular类生成算式的中缀表达式,其中包含8个方法。

 

方法

说明

1

def catFormula(self, operand1, operator, operand2)

链接算式

2

def getRandomIntOperand(self)

返回随机整数操做数

3

def getRandomFractionOperand(self)

返回随机分数操做数

4

def getRandomOperator(self)

返回随机运算符

5

def getOriginFormular(self)

生成整数源算式

6

def insertBracket(self, formular)

插入括号

7

def replaceFraction(self, formular)

带入分数

8

def solve(self)

整合生成算式的后缀表达式,带括号

4.3 计算算式

  使用ComputeFormular类计算算式,经过将中缀表达式转为后缀表达式,使用栈计算结果。

 

 

方法

说明

1

def getPostFormular(self, formular)

中缀表达式转为后缀表达式

2

def calcFormular(self, formular)

计算算式的值

3

def solve(self, formular)

整合计算中缀表达式的值

 

5. 代码示例

5.1 GeneralFormular.getOriginFormular()方法

def getOriginFormular(self):
        '''
        * 生成整数源算式

        * @return {str} 
        '''
        # 经过self.opt.oper_num控制操做数个数,循环调用catFormula()方法构造算式
        tmp = self.getRandomIntOperand()
        for i in range(self.opt.oper_num-1):
            tmp = self.catFormula(tmp, self.getRandomOperator(), self.getRandomIntOperand())

        # 去掉'÷0'
        while(True):
            if '÷0' in tmp:
                tmp = tmp.replace('÷0', '÷'+str(self.getRandomIntOperand()))
            else:
                break

        return tmp

 

5.2 GeneralFormular.insertBracket()方法

def insertBracket(self, formular):
        '''
         * 插入括号

         * @param formular {str} 源算式

         * @return {str} 
        '''
        # print(formular)

        # 若只包含+号 或 只有两个操做数 则不用加括号
        if self.opt.oper_variety <= 2 or self.opt.oper_num == 2:
            return formular
        # 若不包含×÷ 则不用加括号
        if '×' not in formular and '÷' not in formular:
            return formular
        
        # 操做数列表
        operand_list = re.split("[-|+|×|÷]", formular)
        # 操做符列表
        operator_list = re.split("[!0-9]", formular)
        # 去掉空字符
        while '' in operator_list:
            operator_list.remove('')
        # print(operand_list, operator_list)

        # 存储添加括号的算式
        new_formular = ""
        
        # flag表示是否已存在左括号,做用在于构造出一对括号
        flag = 0

        # 添加括号
        for i in range(len(operator_list)):
            oper = operator_list.pop(0)
            # 若下一个符号为 + or - , 则插入括号
            if oper == '-' or oper == '+':
                if flag == 0:
                    new_formular += "("
                    flag = 1
                new_formular += (str(operand_list.pop(0)) + str(oper))
            else:
                new_formular += str(operand_list.pop(0))

                if flag == 1:
                    new_formular += ")"
                    flag = 0
                
                new_formular += str(oper)
            # print(operand_list, operator_list, new_formular)
        
        new_formular += str(operand_list.pop(0))
        if flag == 1:
            new_formular += ")"
        
        return new_formular

 

6. 测试运行

6.1 不包含分数

6.2 包含分数

7. 单元测试

 1 import unittest
 2 from formula import OPT, GeneralFormular, ComputeFormular
 3 
 4 class FormulaUnitTest(unittest.TestCase):
 5     def test_gf_catFormular(self):
 6         '''
 7          * 测试拼接算式 
 8         '''
 9         gf = GeneralFormular(OPT())
10         self.assertEqual(gf.catFormula("12", "+", "34"), "12+34")
11         self.assertEqual(gf.catFormula("23", "+", "456"), "23+456")
12         self.assertEqual(gf.catFormula("1z", "+", "32"), "1z+32")
13 
14     def test_cf_getPostFormular(self):
15         '''
16          * 测试中缀表达式转为后缀表达式
17         '''
18         cf = ComputeFormular()
19         self.assertEqual(cf.getPostFormular("3+7"), "3#7#+")
20         self.assertEqual(cf.getPostFormular("3×(7+2+1)"), "3#7#2#+1#+×")
21         self.assertEqual(cf.getPostFormular("6×(2+1)÷(9-2+3)"), "6#2#1#+×9#2#-3#+÷")
22         self.assertEqual(cf.getPostFormular("6×(2+1)÷0"), "6#2#1#+×0#÷")
23     
24     def test_cf_calcFormular(self):
25         '''
26          * 测试后缀表达式计算为数值 
27         '''
28         cf = ComputeFormular()
29         self.assertEqual(cf.calcFormular("3#7#+"), "10")
30         self.assertEqual(cf.calcFormular("3#7#2#+1#+×"), "30")
31         self.assertEqual(cf.calcFormular("6#2#1#+×9#2#-3#+÷"), "9/5")
32         self.assertEqual(cf.calcFormular("6#2#1#+×0#÷"), "NaN")
33         
34 
35 if __name__ == "__main__":
36     unittest.main()

 

 

8. 性能分析

8.1 GeneralFormular.getOriginFraction()方法

8.2 GeneralFormular.replaceFraction()方法

8.3   GeneralFormular.solve()方法

8.4 ComputeFormular.solve()方法

相关文章
相关标签/搜索