python 利用栈实现复杂计算器
#第五周的作业--多功能计算器
#1.实现加减乘除及括号的优先级的解析,不能使用eval功能,print(eval(equation))
#2.解析复杂的计算,与真实的计算器结果一致
#用户输入 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.左括号一律进运算符栈,右括号一律不进运算符栈,取出栈顶运算符和操作数栈顶的两个连续操作数运算,并将结果存入操作数栈,直到取出左括号为止。

#给一个点,我们能够根据这个点知道一些内容 class Node(object): def __init__(self,val): #定位的点的值和一个指向 self.val=val #指向元素的值 self.next=None #指向的指针 class Stack(object): def __init__(self): self.top=None #初始化最开始的位置 def peek(self): #获取栈顶的元素 if self.top!=None: #如果栈顶不为空 return self.top.val #返回栈顶元素的值 else: return None def push(self,n):#添加到栈中--入栈 n=Node(n) #实例化节点 n.next=self.top #顶端元素传值给一个指针 self.top=n #新入栈的节点作为栈顶元素 return n.val def pop(self): #出栈 if self.top == None: return None else: tmp=self.top.val self.top=self.top.next #栈顶下移一位 return tmp # if __name__=="__main__": # s=Stack() # s.push(1) # s.push(2) # s.push(3) # # print(s.pop()) # print(s.pop()) # print(s.pop())
下面是计算器的代码,引用了上面的栈的模块

#_*_coding:utf-8_*_ #第五周的作业--多功能计算器 import string import re from stack_test import Node,Stack # 定义加法运算 def add(num1,num2): return num1+num2 # 定义减法运算 def sub(num1,num2): return num1-num2 # 定义乘法运算 def mult(num1,num2): return num1*num2 # 定义除法运算 def div(num1,num2): return num1/num2 # 定义运算的操作 operation={ "+":add, "-":sub, "*":mult, "/":div } #判断一个字符串是否是数字 def is_number(s): try: float(s) return True except ValueError: pass try: import unicodedata unicodedata.numeric(s) return True except (TypeError, ValueError): pass return False # 定义运算符的优先级别 weight={ '(':3, '*':2, '/':2, '+':1, '-':1, None:0 } # 进行运算 num1=0 num2=0 result=0#用于表示计算的 data_stack=Stack()#实例化的一个数栈,存放数 oper_stack=Stack()#实例化的一个符号栈,存放+-*/() def deal_data(): p=oper_stack.pop()#把运算符出栈 num2=float(data_stack.pop()) num1=float(data_stack.pop()) result=operation[p](num1,num2) print("%s %s %s临时结果:%s"%(num1,p,num2,result)) print("把计算的结果%s继续存入数栈中"%result) data_stack.push(result) return result while True: equation=input("请输入计算的式子(*提示英文状态下):") # 对输入的算式字符串进行解析,eg:3*5,(99.8-52)*7+6-1.2*41 #1.2-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2)) while equation: cur=re.search(r'((^\d+\.?\d*)|(^\(\-\d+\.?\d*)|\(|\)|\+|\-|\*|/)',equation).group() print("----->",cur) if "(-" in cur:#考虑到负数的情形,如(-5.2) # 一分为二,"("与"-4" # 把左括号存入到符号栈中 bracket=cur[0] print("----->",bracket) print("将%s存入到符号栈中"%bracket) oper_stack.push(bracket) equation=equation[1:] print("剩余的equation:",equation) # 把负数存入到符号栈中 num=cur[1:] print("----->",num) print("将%s存入到数栈中"%num) data_stack.push(num) equation=equation[len(num):] print("剩余的equation:",equation) else:#非负情形 lenth=len(cur) if is_number(cur):#数字则存入数栈 print("将 %s 存入数栈data_stack"%cur) data_stack.push(cur) else:#非数字的符号 if cur=="(":#左括号一律入栈 print("将%s存入到符号栈中"%cur) oper_stack.push(cur) elif cur==")":#右括号则--将取两个数进行运算 deal_data()#处理数据的运算 #(12-5*8)再次判断“(”是否是符号栈的栈顶 while oper_stack.peek()!="(": deal_data() oper_stack.pop()#把左括号出栈 else:#运算符 if oper_stack.peek()==None:#符号栈为空 print("将%s存入到符号栈中"%cur) oper_stack.push(cur) else:#符号栈不为空 if weight[cur]>weight[oper_stack.peek()]:#当前符号优先级“高于”栈顶元素的优先级 print("将%s存入到符号栈中"%cur) oper_stack.push(cur) else:#当前符号优先级“等于|低于”符号栈栈顶元素的优先级 if oper_stack.peek()=="(": print("将%s存入到符号栈中"%cur) oper_stack.push(cur) else: deal_data() while weight[cur]==weight[oper_stack.peek()]: deal_data() print("将%s存入到符号栈中"%cur) oper_stack.push(cur) equation=equation[lenth:] print("剩余的equation:",equation) # 把算式逐个拆解完了,最后处理栈中还剩余的数据 result=deal_data() while oper_stack.peek()!=None: result=deal_data() print("计算的结果为:\033[31;1m%s\033[0m"%result)
你不了解的事情,并不意味着它不发生;
你不知道的事情,也并不意味着它不存在;
学习就是探索未知的东西。