能够识别四则运算的优先级和括号的计算器,其难点在于如何在遇到乘号、除号或者是括号时暂时不计算前面的加法,而先把乘法(除法或者是括号内的计算式)先计算出来,比如1+2*3,如何在读到2的时候不直接和1相加,而是先和3相乘,单看这一点是比较容易的,因为可以再多读一个符号,判断是否为乘号或者是除号,若是,先计算后面的整体,然后接着读一个符号,若还是乘号或者除号,就继续读、继续算,直到读到的不是乘号或者是除号为止。但是若引入括号又该怎么办?一般对于括号中的内容采用递归的方法解决。这就是大致思路,但是到底是先判断括号还是先判断乘除号?可以这样考虑:跟在一个运算符号(也就是+、-、*、/)后面的,要么是一个括号括起来的表达式如+(2+3),要么就是一个数字如+2,这是只需要先判断是否是括号符号"(",若是,则对整个括号内的内容进行递归;若不是(,也就意味着这个运算符号后面跟的是一个数字,则判断这个数字后面的符号是否是乘除号,若是就将其整体递归计算出来,若不是,则直接与前一个数字进行加减操作。
先贴出只能对括号进行处理的代码(不能判断乘除的优先级)(两个计算器我各自写成了一个函数,都可以直接调用):
这里是先单独读取第一个数字(整体),然后循环读取一个符号和符号后的数字(整体)(这里的整体是指被括号括起来的部分),对每个整体分别进行计算后再将整体之间的内容进行计算。用到了递归。
def simpleArithmetic():
#x存储表达式
#loc记录当前读取位置
#count用于将括号和括回进行匹配
#locStart记录被括号括起来的整体的起始位置,locEnd则记录结束位置(不包括那一对括号)
x = input("input your expression")
def cal(exp):
loc = 0
count = 0
#读入第一个数字/整体(被括号括起来的)
firstNum = exp[loc]
if firstNum != "(":
result = int(firstNum)
loc += 1
else:
locStart = loc + 1
count += 1 # 为了将( 与 ) 进行匹配
while count != 0:
loc += 1
if exp[loc] == "(":
count += 1
elif exp[loc] == ")":
count -= 1
locEnd = loc
loc += 1
result = cal(exp[locStart:locEnd])
#读取后面的符号和数字/整体
while loc < len(exp):
operator = exp[loc]
loc += 1
secNum = exp[loc]
if secNum != "(":
loc += 1
else:
locStart = loc+1
count += 1#为了将( 与 ) 进行匹配
while count != 0:
loc += 1
if exp[loc] == "(":
count += 1
elif exp[loc] == ")":
count -= 1
locEnd = loc
loc += 1
secNum = cal(exp[locStart:locEnd])
if operator == "+":
result += int(secNum)
elif operator == "-":
result -= int(secNum)
elif operator == "*":
result = result * int(secNum)
else:
result = result / int(secNum)
return result
return cal(x)
然后是能够识别优先级和括号的代码:
注释里的整体就是指被乘除号连接起来的整体如1+2*3*4中的2*3*4
def smartArithmetic1():
#x存储表达式
#loc记录当前读取位置
#count用于将括号和括转进行匹配
#locStart记录被括号括起来的整体的起始位置,locEnd则记录结束位置(不包括那一对括号)
x = input("input your expression")
def cal(exp):
loc = 0
count = 0
# 读入第一个数字/整体(被括号括起来的)
firstNum = exp[loc]
if firstNum != "(":
result = int(firstNum)
loc += 1
else:
locStart = loc + 1
count += 1 # 为了将( 与 ) 进行匹配
while count != 0:
loc += 1
if exp[loc] == "(":
count += 1
elif exp[loc] == ")":
count -= 1
locEnd = loc
loc += 1
result = cal(exp[locStart:locEnd])
while loc < len(exp):
operator = exp[loc]
loc += 1
#完善第一个整体,即若后面有跟*或者/时读进来计算为一个整体
while operator == "*" or operator =="/":
secNum = exp[loc]
if secNum != "(":
loc += 1
else:
locStart = loc+1
count += 1#为了将( 与 ) 进行匹配
while count != 0:
loc += 1
if exp[loc] == "(":
count += 1
elif exp[loc] == ")":
count -= 1
locEnd = loc
loc += 1
secNum = cal(exp[locStart:locEnd])
if operator == "*":
result = result * int(secNum)
else:
result = result / int(secNum)
if loc >= len(exp):
break
operator = exp[loc]
loc += 1
#加号或者减号
operator1 = operator
if loc >= len(exp):
break
secNum = exp[loc]
if secNum != "(":
secNum = int(secNum)
loc += 1
else:
locStart = loc + 1
count += 1 # 为了将( 与 ) 进行匹配
while count != 0:
loc += 1
if exp[loc] == "(":
count += 1
elif exp[loc] == ")":
count -= 1
locEnd = loc
loc += 1
secNum = cal(exp[locStart:locEnd])
#完善第二个加数/减数
if loc < len(exp):
operator = exp[loc]
loc += 1
flag = False
while operator == "*" or operator =="/":
flag = True
thirdNum = exp[loc]
if thirdNum != "(":
loc += 1
else:
locStart = loc+1
count += 1#为了将( 与 ) 进行匹配
while count != 0:
loc += 1
if exp[loc] == "(":
count += 1
elif exp[loc] == ")":
count -= 1
locEnd = loc
loc += 1
thirdNum = cal(exp[locStart:locEnd])
if operator == "*":
secNum = secNum * int(thirdNum)
else:
secNum = secNum / int(thirdNum)
if loc >= len(exp):
break
operator = exp[loc]
loc += 1
if not flag:
loc -= 1
if operator1 == "+":
result += int(secNum)
else:
result -= int(secNum)
if loc >= len(exp):
break
return result
return cal(x)
测试效果:(目前这个针对了整数,浮点数还没测试,可以把int改为float试一下)
博主写python没多久,可能有些不规范(第二个代码里面有很多重复的代码,比如读取整体和完善整体的代码,可以整合成函数),还请多多见谅23333。还有就是这个代码没有测试很多用例,可能会有bug,如果有请在评论区发出有错的测试用例,thx。
后面还有一篇用栈和递归实现同样功能的文章,这篇文章里面的代码要规整一些,其中有借鉴别人的代码https://blog.csdn.net/KevinLML/article/details/86590697