python 入坑路-day5作业 模拟计算器

需求分析

day 5作业:模拟计算器开发
作者:keven

作业需求:
实现加减乘除及拓号优先级解析
用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,
必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),
运算后得出结果,结果必须与真实的计算器所得出的结果一致

流程:
1.解析字符串,区别 减号,与 复数。
2.利用栈方式,新建数字栈,符号栈。
3.调用,简单加,减,乘,除函数,调用符号优先级判断函数。
a、当栈顶符号的优先级大于、等于,入栈符号的优先级时,数字栈谈出末尾两个数字进行计算。
b、当栈顶符号的优先级 小于,入栈符号的优先级时,不做计算。
c、当遇到右括号时,依次弹出数字栈的数字,及符号栈的符号,进行计算。知道遇到左括号。
4.返回结果

import re

s="1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )"

#处理字符串, 主要是区别 减号,和 负数
def init_action(s):
    #print(s)
    s=re.sub(" ","",s)
    print(s)
    init_l=[i for i in re.split("(\-\d+\.*\d*)",s) if i]
    print(init_l)
    expression_l=[]
    while True:
        if len(init_l) == 0: break
        exp=init_l.pop(0)
        if len(expression_l) == 0 and re.search("^\-\d+\.*\d*$",exp):
            expression_l.append(exp)
            continue
        # if len(expression_l) > 0:
        #     if re.search("[\+\-\*\/\(\)]]",expression_l[-1]):
        #         expression_l.append(exp)
        #         continue
        if len(expression_l) > 0:
            if re.search("^[\-][\d+]",exp) and  not re.search("\d+",expression_l[-1]):
                expression_l.append(exp)
                continue

        newl=[i for i in re.split("([\+\-\*\/(\)])",exp) if i]
        expression_l+=newl

    return expression_l

#程序主体
def main(expression_l):
    #print("main",expression_l)
    number_stack=[]  #定义数字栈
    symbol_stack=[] #定义符号栈
    for ele in expression_l:  #循环 出来后的字段
        # print("*"*30)
        # print("number_stack",number_stack)
        # print("symbol_stack",symbol_stack)
        # print("没有入栈",ele)
        ret=is_symbol(ele) #判断字符是否是 运算字符,
        if not ret: #如果不是运算符,压入数字栈
            #print(ele)
            ele=float(ele)
            number_stack.append(ele)
        else:
            while True: #如果是运算字符
                if len(symbol_stack) == 0: #当运算符栈为空,无条件压入栈
                    symbol_stack.append(ele)
                    break

                res= priority(symbol_stack[-1],ele) #调用判断运算符 优先级函数,

                if res == "<":  #当后来入站优先级大于 运算符栈顶的运算符时,压入站内
                    symbol_stack.append(ele)
                    break
                elif res == "=": # 优先级相等时,弹出栈顶运算符,准备计算
                    symbol_stack.pop()
                    break
                elif res == ">": # 当优先级小于,运算符栈顶时 开始计算
                    symbol=symbol_stack.pop()
                    num2=number_stack.pop()
                    num1=number_stack.pop()
                    number_stack.append(calculate(num1,symbol,num2))
        #print(number_stack,symbol_stack)
    else:

        while len(symbol_stack) > 0: #执行完成循环后,判断运算符内是否还有运算符,如果有继续计算
            symbol = symbol_stack.pop()
            num2 = number_stack.pop()
            num1 = number_stack.pop()
            number_stack.append(calculate(num1, symbol, num2))
        #print(number_stack,symbol_stack)


    return number_stack,symbol_stack

def priority(top_sym,wait_sym): #定义判断字符优先级函数,
    #print(top_sym,wait_sym)
    level1=["+","-"]
    level2=["*","/"]
    level3=["("]
    level4=[")"]
    if top_sym in level1:
        if wait_sym in level2 or wait_sym in level3:
            return "<"
        else:
            return ">"

    elif top_sym in level2:
        # if wait_sym in level1:
        #     return ">"
        # elif wait_sym in level2:
        #     return ">"
        # elif wait_sym in level3:
        #     return "<"
        # elif wait_sym in level4:
        #     return ">"
        # else:
        #     return ">"
        if wait_sym in level3:
            return "<"
        else:
            return ">"


    elif top_sym in level3:
        if wait_sym in level4:
            return "="
        else:
            return "<"


def is_symbol(element):
    #print("sybol",element)
    res=False
    symbol=["+","-","*","/","(",")"]
    if element in symbol:
        res=True
    #print(res)
    return res

def calculate(num1,symbol,num2): #定义简单的 4四则运算函数。
    res=0
    if symbol == "+":
        res=num1+num2
    elif symbol == "-":
        res=num1-num2
    elif symbol == "*":
        res=num1*num2
    elif symbol == "/":
        res=num1/num2
    return res

s1=init_action(s)
print(s1)
s2=main(s1)
print(s2)
print("eval 计算结果:{}".format(eval(s)))

 

posted @ 2018-01-25 15:38  东郭仔  阅读(122)  评论(0)    收藏  举报