软件工程第五次作业--四则运算

题目

   (1)能自动生成小学四则运算题目;

   (2)能支持任意分数的四则运算;

   (3)能支持任意括号运算

思路

  根据参数生成不定长度的表达式,以及能控制是否生成分数,能生成任意数量的中缀表达式,支持四则运算,括号运算以及分数运算

  构造函数接口  def __init__(self, exps_num=10, num_l=1, num_r=10, exp_limit_len=10, has_fraction=True)

  提供接口生成中缀表达式,返回表达式数据集   def create_express(self)

  提供接口将中缀表达式化为后缀表达式  def get_postfix(self, exp)

  提供接口将后缀表达式进行计算并返回结果  def cal_express(self, exp)

  提供接口以用户友好方式显示中缀表达式  def get_showExp(self, exp)


源代码
# -*- coding: utf-8 -*-
# author: 'boliang'
# date: 2018/4/18 21:04

import profile
import random
from fractions import Fraction

class Solution(object):
def __init__(self, exps_num=10, num_l=1, num_r=10, exp_limit_len=10, has_fraction=True):
self.__exps_num = exps_num
self.__has_fraction = has_fraction
self.__exp_limit_len = exp_limit_len
self.__num_l = num_l
self.__num_r = num_r

# 生成中缀表达式
def create_express(self):
exps = []
num = self.__exps_num
while num > 0:
num_len = random.randint(2, self.__exp_limit_len)
tmp_len = num_len - 1
exp = [self.__get_num(self.__has_fraction)]
while tmp_len > 0:
# 1为+,2为-,3为*,4为/
op_flag = random.randint(1, 4)
if op_flag == 1:
exp.append('+')
elif op_flag == 2:
exp.append('-')
elif op_flag == 3:
exp.append('*')
else:
exp.append('/')
exp.append(self.__get_num(self.__has_fraction))
tmp_len -= 1

brackets = random.randint(0, int(len(exp)/8))
while brackets > 0:
if self.__set_bracket(exp, num_len):
brackets -= 1

exps.append(exp)
num -= 1

return exps


def __set_bracket(self, exp, num_len):
index_a = 0
index_b = 0
while index_a == index_b:
rec = list(map(lambda x:random.randint(0, num_len-1), range(2)))
index_a = min(rec) + 1
index_b = max(rec) + 1

cal = 0
length = len(exp)
for i in range(length):
if type(exp[i]) != type('+'):
cal += 1

if cal == index_a:
if i+1 <= length and exp[i+1] == ')':
return False
exp.insert(i, '(')

cal = 0

for i in range(len(exp)):
if type(exp[i]) != type('+'):
cal += 1

if cal == index_b:
if i-1 >= 0 and exp[i-1] == '(':
return False
exp.insert(i+1, ')')
break

return True

# 生成一个数, 包括分数
def __get_num(self, has_fraction=True):

# 生成包括有分数
if has_fraction:
# 80%几率为整数
flag = random.randint(1, 10)
if flag <= 8:
return self.__get_num(False)
else:
return Fraction(self.__get_num(False), self.__get_num(False))
# 生成整数
else:
return random.randint(self.__num_l, self.__num_r)

# 计算后缀表达式
def cal_express(self, exp):
record = []
for val in exp:
if type(val) == type('+'):
b = record.pop(-1)
a = record.pop(-1)
if val == '+':
record.append(a+b)
elif val == '-':
record.append(a-b)
elif val == '*':
record.append(a*b)
else:
record.append(a/b)
else:
record.append(val)

return record[0]

# 通过中缀表达式得到后缀表达式
def get_postfix(self, exp):
l_ops = {
'(': 1, '*': 5, '/': 5,
'+': 3, '-': 3, ')': 6
}

r_ops = {
'(': 6, '*': 4, '/': 4,
'+': 2, '-': 2, ')': 1
}

op_stack = []
post_stack = []
for val in exp:
if type(val) != type('+'):
post_stack.append(val)
elif len(op_stack) > 0:
while len(op_stack) > 0 and l_ops[op_stack[-1]] >= r_ops[val]:
if op_stack[-1] != '(' and op_stack[-1] != ')':
post_stack.append(op_stack.pop(-1))
else:
op_stack.pop(-1)

op_stack.append(val)
else:
op_stack.append(val)

while len(op_stack) > 0:
if op_stack[-1] != '(' and op_stack[-1] != ')':
post_stack.append(op_stack.pop(-1))
else:
op_stack.pop(-1)

return post_stack


def get_showExp(self, exp):
op = {'+': '+', '-': '-', '*': '×', '/': '÷', '(':'(', ')':')'}
jud_fun = lambda val: str(val) if type(val) != type('+') else op[val]
return ' '.join(map(jud_fun, exp))


# 测试函数
def test():
# 1. 测试程序自动生成10组表达式数据(包括分数和括号运算)
# 2. 测试通过中缀表达式计算得到后缀表达式
# 3. 根据后缀表达式计算结果(包括分数)

# 设置接口参数
# 表达式个数
express_num = 10
# 生成的数的下界
num_l = 1
# 生成的数的上界
num_r = 10
# 表达式的数字个数
exp_limit_len = 10
# 是否会生成分数
has_fraction = True

sol = Solution(express_num, num_l, num_r, exp_limit_len, has_fraction)

# 生成中缀表达式
exps = sol.create_express()


for ind, exp in enumerate(exps):
print('.......................................')
print('第{0}条表达式:{1}'.format(ind+1, exp))
tmp = sol.get_postfix(exp)
print('后缀表达式为:{0}'.format(tmp))
print('用户界面中显示的表达式:{0}'.format(sol.get_showExp(exp)))
print('运算结果为:{0}'.format(sol.cal_express(tmp)))
print('.......................................')


if __name__ == '__main__':
profile.run('test()')

根据单元测试,测试结果如下

 

效能分析, 运用Python profile库

 

PSP表格

 预计耗时(分钟)是实际耗时(分钟)
Planning计划1010
Estimate估计这个任务需要多少时间100100
Development开发120240
Analysis需求分析510
Design Spec生成设计文档323
Design Review设计复审(和同事审核设计文档)22
Coding Standerd代码规范(为目前的开发制定合适的规范)33
Design具体设计510
Coding具体编码3060
Code Review代码复审510
Text测试(自测,修改代码,提交修改)1030
Reporting报告1020
Text Report测试报告1020
Size Measurement计算工作量55
Postmortem & Process Improvement Plan事后总结,并提出过程改进计划55
Sum合计215420
 
 

转载于:https://www.cnblogs.com/lbliang/p/8878753.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值