梁梦瑶 20190919-6 四则运算

此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/7631

git地址:https://e.coding.net/sxl357/f4.git

功能一:

做这个题的时候开始完全没有思路,如何让程序计算一个表达式,我们通过查阅资料,利用搜索引擎,发现如果输入一个表达式是无法算出结果的,需要先将中缀表达式转换为后缀表达式,然后将后缀表达式的结果计算出来。在这一部分我们花费了很多时间,先去了解了如何将中缀表达式转换为后缀表达式。

具体步骤:

需要一个存放操作符的栈op_stack,输出结果的列表output
步骤:
从左到右遍历表达式:
1. 若是数字,直接加入到output
2. 若是操作符,比较该操作符和op_stack中操作符的优先级,若优先级大于op_stack中的,则压入到op_stack中
    否则,将op_stack中优先级大于或等于该操作符优先级的所有操作符加入到output中,然后压入op_stack中
3. 若是左括号,压入到op_stack中
4. 若是右括号,将op_stack中所有左括号前面的操作符加入到output中
重复上面的步骤
然后将这一理论知识转换为具体的python代码,具体如下:
def make_Expression(s):
    operations=[]
    result=''
    front={'+':1,'-':1,'*':2,'/':2,'(':0,')':3}
    for i in s:
        if i in ['+','-','*','/','(',')']:#判断是否是操作符
            if i=='(':#遇到左括号,将其直接放入栈中
                operations.append(i)
            elif i==')':#遇到右括号,持续将栈顶元素弹出并输出,直至遇到左括号
                while (len(operations)>0 and operations[-1]!='(' ):#-1表示列表的最后一个元素,即栈顶
                    p=operations.pop()
                    result+=p
                operations.pop()#左括号只弹出不输出
            elif len(operations)==0:#栈空,直接入栈
                 operations.append(i)
            elif front[operations[-1]]>=front[i]:#判断栈顶元素和操作符的优先级别
                while len(operations)>0 and front[operations[-1]]>=front[i]:#持续将栈顶元素弹出并输出,直至遇到低于或等于此操作符的优先级别
                    p=operations.pop()
                    result+=p
                operations.append(i)
            else:
                operations.append(i)
        else:
            result+=i#若是数,直接输出
    while len(operations)>0:#将栈中的所有元素依次弹出
        p=operations.pop()
        result+=p
    return result#返回后缀表达式

转换为后缀表达式之后就可以计算值了:

具体步骤:

需要一个存放中间结果的栈num_stack
步骤:
从左到右遍历表达式:
1. 若是数字,压入到num_stack中
2. 若是操作符,取出num_stack中的前两个元素,第二个是表达式左边的操作数,计算表达式的值,将求值结果压入到num_stack中
def make_Value(s):
    lists=[]
    for i in s:
        if i in ['+','-','*','/']:
            b=float(lists.pop())#先弹出的是b,下个弹出的是a
            a=float(lists.pop())
            c=0
            if i=='+':#判断做哪则运算
                c=a+b
            elif i=='-':
                c=a-b
            elif i=='*':
                c=a*b
            else:
                c=a/b
            lists.append(c)#得到的结果压入栈中
        else:
            lists.append(i)
    return lists[0]

这部分最大的障碍就是如何自动生成20道题,我们思考了两天无果,找了师哥的代码进行了学习和理解,最终搞明白了原理,又自己进行了修改,最终自己敲了一遍进行了运行。

    def expre(self):#在类里定义函数必须传入self,指的是类实例对象本身
        exp = []
        for j in range(0,7):  #range(a)=[0,1,2,3,...,a-1]
            if j % 2 != 0:#通过模2,生成带3个运算符4个10以内数字的表达式
                operators = ['+', '-', '*', '/']
                exp.append(operators[randint(0, len(operators) - 1)])  #随机生成运算符
            else:
                exp.append(str(randint(1, 9)))  #随机生成操作数
        is_need_brackets = randint(0, 1) # 判断是否要括号
        if is_need_brackets:#添加括号
            expression = ''.join(self.make_brackets(exp))#.join()将序列中的元素以指定的字符连接生成一个新的字符串
                                                                #加括号时,调用生成括号表达式的函数,得到一个带括号的运算式
        else:#不添加括号
            expression = ''.join(exp)
        return expression

 

运行截图:

 

 

 

 功能二

生成括号表达式部分,我们选用了枚举的方法,对于四个操作数三个运算符,最多可以有两对括号,括号的排列方式有10种情况,我们是选择一一把它列举出来。

    # 生成括号表达式
    def make_brackets(self,exp):#传入由运算符和数字组成的列表
        expression = []
        # 可能有一对括号,也可能有两对括号,所以最多有11个位置可以添加括号
        #经过枚举,共有10种可能的添加方式
        # 0表示直接将运算符或数字传入生成式,1表示在生成式加入左括号,2表示在生成式加入右括号,-1表示不作任何处理
        judge_position= [
                              [1, 0, 0, 0, 2, 0, 0, 0, 0, -1, -1],
                              [1, 0, 0, 0, 0, 0, 2, 0, 0, -1, -1],
                              [0, 0, 1, 0, 0, 0, 2, 0, 0, -1, -1],
                              [0, 0, 1, 0, 0, 0, 0, 0, 2, -1, -1],
                              [0, 0, 0, 0, 1, 0, 0, 0, 2, -1, -1],
                              [1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 2],
                              [1, 1, 0, 0, 0, 2, 0, 0, 2, 0, 0],
                              [1, 0, 0, 1, 0, 0, 0, 2, 2, 0, 0],
                              [0, 0, 1, 1, 0, 0, 0, 2, 0, 0, 2],
                              [0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 2]
                          ]
        position = randint(0,9)
        if exp:
            i = 0
            for j in judge_position[position]:#调用上述列表
                if j ==0:
                    expression.append(exp[i])
                    if i < len(exp):
                        i += 1
                elif j ==1:
                    expression.append('(')
                elif j ==2:
                    expression.append(')')
        return expression

 

 

 

 功能三

通过分析此题,生成表达式后发现首先要规范化输出

# 答案与题目横向对齐,使输出规范化,实现功能三
def normal(num):
    i = 0
    while i < num:
        generate = Expression()
        expression = generate.expre()
        expression1 = make_Expression(expression)  # 将中缀表达式转换为后缀表达式
        result = make_Value(expression1)  # 计算后缀表达式的值
        expression=expression+"="
        print('%-15s %-15s' % (expression, result))  # 规范输出格式
        i += 1

然后需要通过命令行参数传入-c执行这一部分,且要求需要输入正整数

def main(argv):
    if '-c' in sys.argv:  # 实现功能三
        count=float(sys.argv[2]) # 获取生成题目的个数
        if count >=1:
            normal(count)
        else:
            print("题目数量必须是正整数。")
    else:
        question()#实现功能一二

需要输入正整数方面功能实现:

 

 

 

 功能三全部实现:

结论: 

这是第一次的两人结对的合作,感觉两人合作确实会碰触思想的火花,对同一个问题能够收获多样化的思路和方法,也能看到我的小伙伴在问题上坚持不懈的毅力,学到了很多知识,收获最大的就是规范化了我的代码书写,之前的我不太严谨,通过这一个星期的共同学习努力,规范化了我自己,感谢我的小伙伴。

 

 结对伙伴:宋晓丽

结对地点:星华公寓622宿舍

posted @ 2019-09-25 17:01  summerkingy  阅读(147)  评论(0编辑  收藏  举报