zoukankan      html  css  js  c++  java
  • 梁梦瑶 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宿舍

  • 相关阅读:
    数据库设计主键定义思考
    dotnet(C#)的面试题,大家共享一下
    一些有创意的SQL语句
    asp.net(c#) 服务器探针
    存储过程共有三种返回值
    如何删除表中的重复记录?等等常用SQL语句的积累
    一般存储过程示例
    关于utf8,unicode字符集
    在Asp.net里利用DIV层元素弹出窗体
    数据库主键设计思考
  • 原文地址:https://www.cnblogs.com/summerkingy/p/11584602.html
Copyright © 2011-2022 走看看