第三周作业(6)——四则运算试题生成

作业要求地址:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2148

一、具体要求

具体实现功能如下:

功能1:支持出题4个数的四则运算题目,所有题目要求作者有能力正确回答。(+10)

功能2:在功能1的基础上,支持括号。(+15)

功能3:限定题目数量,“精美”打印输出,且要避免重复,最好能输出到.txt文件中。且对输入题目数进行限定,题目数量必须是正整数。(+10)

功能4:支持分数出题和运算。(不完成此题不倒扣分数)

功能5:可把程序改成GUI版/web版/移植为android,ios版。

此次作业完成是以“结对编程”的形式完成,我的伙伴是段晓睿,她的博客地址为:https://www.cnblogs.com/ruidxr/

二、运行截图

本次编程采用面向过程的方法,首先随机生成四则运算表达式,然后将算式转为逆波兰表达式,再计算逆波兰表达式的值即最后算式结果。

功能1、2运行截图:

功能3运行截图:

功能4对分数进行计算暂未能实现。

三、代码分析:

功能实现过程中,主要的是利用栈实现逆波兰和计算逆波兰的过程,重要代码片段如下:

1.随机生成算式

    用随机生成函数random控制生成数字和运算符,随机生成0—3实现四个运算符的随机生成,功能2插入括号是难点,我们例举了括号出现的情况,将生成的情况编号,进行特定位置插入。

def create_equation():      # 随机生成算式
    eq = []

    for i in range(3):
        eq.append(random.randint(0, 10))
        eq.append(operator[random.randint(0, 3)])
    eq.append(random.randint(0, 10))
    p = random.randint(1, 5)
    if p is 1:
        eq.insert(0, "(")
        eq.insert(4, ")")
    elif p is 2:
        eq.insert(0, "(")
        eq.insert(6, ")")
    elif p is 3:
        eq.insert(2, "(")
        eq.insert(6, ")")
    elif p is 4:
        eq.insert(2, "(")
        eq.append(")")
    elif p is 5:
        eq.insert(4, "(")
        eq.append(")")
    return eq
View Code

2.实现逆波兰

    “逆波兰”我印象中没有听说过,后来经过网上学习才知道原来逆波兰表达式就是后缀表达式,这个在数据结构中印象还是挺深刻的,但具体实现起来还是比较困难,上网进行了多次查询。逆波兰表达式的转换主要和优先级有关,为运算符优先级提前定义编号,可比较优先级的大小。

def reverse_polish(equation):       # 将算式转换为逆波兰表达式
    result = []
    c = []
    slist = [i for i in equation]

    for item in slist:
        if item in range(0, 100):
            result.append(item)
        elif not c and item in cal.keys():
            c.append(item)
            continue
        elif c and item in cal.keys():
            for x in range(c.__len__()):
                z = c[-1]
                temp = cal[z] if z in cal else cal1[z]
                if temp >= cal[item]:
                    result.append(c.pop())
                else:
                    c.append(item)
                    break
            if not c:
                c.append(item)
        elif item is ")":
            for x in range(c.__len__()):
                if c[-1] == "(":
                    c.pop()
                    break
                else:
                    result.append(c.pop())
        elif item is "(":
            c.append(item)
        # print(result,c)
    for x in range(c.__len__()):
        result.append(c.pop())
    return result
View Code

3.计算逆波兰表达式  

def calculate(re_equation):         # 计算逆波兰表达式
    stack = PyStack()
    sumEnd = 0

    if len(re_equation) is 0:
        return sumEnd
    for i in re_equation:
        if i in range(0, 100):
            stack.push(float(i))
        elif '+' is i:
            a = stack.pop()
            b = stack.pop()
            stack.push(b + a)
        elif '-' is i:
            a = stack.pop()
            b = stack.pop()
            stack.push(b - a)
        elif '*' is i:
            a = stack.pop()
            b = stack.pop()
            stack.push(b * a)
        elif '÷' is i:
            a = stack.pop()
            b = stack.pop()
            if a == 0:
                return False             #print('%d/%d分子不能为0' % (b, a))
            else:
                stack.push(b / a)
    return stack.pop()
View Code

4.栈

建立栈的时候比较费时间,开始的时候我们都无从下手,后来参考模板进行改写。

class PyStack(object):      #自定义栈

    def __init__(self, initSize = 20, incSize = 10):
        self.initSize = incSize
        self.incSize = incSize
        self.stackList = []
        self.top = self.bottom = 0

    def push(self, ele):
        if self.top-self.bottom >= self.initSize:
            self.incSize += self.initSize
        self.stackList.append(ele)
        self.top += 1

    def pop(self):
        if self.top-self.bottom > 0:
            self.top -= 1
            ret = self.stackList.pop()
            return ret
        else:
            return None

    def len(self):
        return self.top-self.bottom
View Code

四、总结:

     本次结对编程过程虽然有过争论,僵持,但总体还是比较和谐,Python是我不太熟悉的语言,刚开始我们分析了一下题目要求,大致列出每个功能实现的方法,之后我就进行了加紧学习。接触到python才感受到它有多么强大,很容易上手,代码可读性非常高,索性python运用起来比较好上手,我也算及时赶上了进度,代码规范的时候,我们在python书写的基本规范上进行进一步讨论,编写过程中相互监督,也是有了这次机会,我才知道自己代码编写有许多小毛病,在队友的提醒下,及时改正。两个人结对编程刚开始的时候感觉效率不是很高,但是经过几天的默契培养之后,明显感觉效率提高了好多。自己编代码经常会分析问题的时候屡不清思路,但是两个人的时候就很少会出现这个问题,一个人领航,一个人写代码,遇到纠结的地方及时讨论、分析、解决。代码编程坏习惯也改正了不少。

五、合作过程

工作地点:星华公寓B201

照片:

六、版本控制

git地址:https://git.coding.net/liu-xin/f4.git

原文地址:https://www.cnblogs.com/liu-xin1995/p/9746337.html