import math
def findNextOpr(txt):
if len(txt)<=0 or not isinstance(txt,str):
return "type error: findNextOpr"
# --- YOU CODE STARTS HERE
if type(txt) == str:
opr_list = ["+", "-", "*", "/", '^']
for i in range(len(txt)):
if txt[i] in opr_list:
return(i)
return(-1)
# --- CODE ENDS HERE
def isNumber(txt):
if not isinstance(txt, str):
return "type error: isNumber"
if len(txt)==0:
return False
# --- YOU CODE STARTS HERE
if type(txt) == str:
try:
float(txt)
return True
except ValueError:
return False
def getNextNumber(expr, pos):
if len(expr)==0 or not isinstance(expr, str) or pos<0 or pos>=len(expr) or not isinstance(pos, int):
return None, None, "type error: getNextNumber"
# --- YOU CODE STARTS HERE
txt = expr[pos:]
oprPos = findNextOpr(txt)
if oprPos != -1:
if isNumber(txt[:oprPos]) == True:
return float(txt[:oprPos]), txt[oprPos], oprPos+pos
else:
return None, txt[oprPos], oprPos+pos
else:
if isNumber(txt):
return float(txt), None, None
else:
return None,None,None
# --- CODE ENDS HERE
def exeOpr(num1, opr, num2):
#This function is just an utility function for calculator(expr). It is skipping type check
if opr=="+":
return num1+num2
elif opr=="-":
return num1-num2
elif opr=="*":
return num1*num2
elif opr=="/":
return num1/num2
elif opr=="^":
return num1**num2
else:
return "error in exeOpr"
def calculator(expr):
if len(expr)<=0 or not isinstance(expr,str):
return "error"
expr = expr.strip()
if expr[0]!="-":
newNumber, newOpr, oprPos = getNextNumber(expr, 0)
else:
newNumber, newOpr, oprPos = getNextNumber(expr, 1)
newNumber *= -1
if newNumber is None:
return "error"
elif newOpr is None:
return newNumber
elif newOpr=="+" or newOpr=="-":
mode="add"
addResult=newNumber
mulResult=None
expResult=None
elif newOpr=="*" or newOpr=="/":
mode="mul"
addResult=0
mulResult=newNumber
expResult=None
elif newOpr=="^":
mode="exp"
expResult=newNumber
addResult=0
mulResult=None
pos=oprPos+1
opr=newOpr
oldopr=None
while True:
newNumber, newOpr, oprPos = getNextNumber(expr, pos)
if newNumber is None:
return "input error: line B in calculator"
elif newOpr is None:
if mode=='add':
if opr=='*':
return exeOpr(addResult, oldopr, mulResult*newNumber)
elif opr=='/':
return exeOpr(addResult, oldopr, mulResult/newNumber)
else:
return exeOpr(addResult, opr, newNumber)
elif mode=='mul':
if expResult==None:
expResult=0
if mulResult==None:
mulResult=0
return addResult + exeOpr(mulResult, opr, newNumber)
elif mode=="exp":
if expResult<0:
expResult=exeOpr(expResult,opr,newNumber)
if expResult>0:
expResult=-1*expResult
else:
expResult=exeOpr(expResult,opr,newNumber)
if mulResult!=0 and (oldopr=='*' or oldopr=='/'):
mulResult=exeOpr(mulResult,oldopr,expResult)
expResult=0
elif newOpr=='+' or newOpr=='-':
if expResult==None:
expResult=0
if mulResult==None:
mulResult=0
if mode=='add':
addResult = exeOpr(addResult, opr, newNumber)
mulResult = 0
expResult= 0
elif mode=='mul':
addResult += exeOpr(mulResult, opr, newNumber)
mulResult = 0
expResult= 0
elif mode=='exp':
if expResult<0:
expResult=exeOpr(expResult,opr,newNumber)
if expResult>0:
expResult=-1*expResult
addResult+=expResult
else:
addResult+=exeOpr(expResult,opr,newNumber)
if oldopr=='*' or oldopr=='/':
expResult=exeOpr(expResult,opr,newNumber)
mulResult=exeOpr(mulResult,oldopr,expResult)
addResult+=mulResult
mulResult = 0
expResult = 0
mode='add'
elif newOpr=="*" or newOpr=="/":
if mode=='add':
if opr=='-':
oldopr='-'
mulResult = newNumber
elif opr=='+':
#print('here1')
oldopr='+'
mulResult = newNumber
mode='mul'
else:
mulResult = newNumber
elif mode=='mul':
mulResult = exeOpr(mulResult, opr, newNumber)
elif mode=='exp':
if expResult<0:
expResult=exeOpr(expResult,opr,newNumber)
if expResult>0:
expResult=-1*expResult
else:
expResult=exeOpr(expResult,opr,newNumber)
if mulResult !=0 and (oldopr=='*' or oldopr=='/'):
mulResult=exeOpr(mulResult,oldopr,expResult)
expResult=0
else:
mulResult=expResult
expResult=0
mode='mul'
elif newOpr=='^':
if mode=='add':
if expResult==None:
expResult=0
if mulResult==None:
mulResult=0
if opr=='-':
expResult = -newNumber
else:
expResult = newNumber
oldopr=opr
elif mode=='mul':
expResult=newNumber
oldopr=opr
mode='exp'
if oprPos==None:
break
pos=oprPos + 1
opr=newOpr
if mulResult== None:
mulResult=0
if expResult==None:
expResult=0
return addResult+mulResult+expResult
以上是我的函数计算器代码,没有错误,但是当我运行代码并尝试 计算器('-5 + 60/3 ^ 3 * 4-2 * 4 ^ 2') 我得到35.888888888888886,但答案应该是-28.11111111111111 我的代码中有人找不到我的错误吗? 我认为它可能在计算器部分中,因为其他所有内容在测试中都可以正常运行,但我找不到位置。
有人告诉我,在课堂上解决问题的一种方法是使用节点/堆栈类可能会有所帮助,但是除了创建另一个类之外,还有其他解决方案吗?
答案 0 :(得分:1)
在calculator
大循环中,当opr
为-
时,您忘记更改mulResult
的符号。
为了调试它,我在exeOpr
函数中添加了一条打印语句,以便我们可以看到计算器在每个步骤中所做的事情。通过查看部分结果很容易确定。
完整的新代码如下:
import math
def findNextOpr(txt):
if len(txt) <= 0 or not isinstance(txt, str):
return "type error: findNextOpr"
# --- YOU CODE STARTS HERE
if type(txt) == str:
opr_list = ["+", "-", "*", "/", '^']
for i in range(len(txt)):
if txt[i] in opr_list:
return (i)
return (-1)
# --- CODE ENDS HERE
def isNumber(txt):
if not isinstance(txt, str):
return "type error: isNumber"
if len(txt) == 0:
return False
# --- YOU CODE STARTS HERE
if type(txt) == str:
try:
float(txt)
return True
except ValueError:
return False
def getNextNumber(expr, pos):
if len(expr) == 0 or not isinstance(expr, str) or pos < 0 or pos >= len(expr) or not isinstance(pos, int):
return None, None, "type error: getNextNumber"
# --- YOU CODE STARTS HERE
txt = expr[pos:]
oprPos = findNextOpr(txt)
if oprPos != -1:
if isNumber(txt[:oprPos]):
return float(txt[:oprPos]), txt[oprPos], oprPos + pos
else:
return None, txt[oprPos], oprPos + pos
else:
if isNumber(txt):
return float(txt), None, None
else:
return None, None, None
# --- CODE ENDS HERE
def exeOpr(num1, opr, num2):
# This function is just an utility function for calculator(expr). It is skipping type check
print("%s %s %s" % (num1, opr, num2)) # <==== DEBUGGING PRINT
if opr == "+":
return num1 + num2
elif opr == "-":
return num1 - num2
elif opr == "*":
return num1 * num2
elif opr == "/":
return num1 / num2
elif opr == "^":
return num1 ** num2
else:
return "error in exeOpr"
def calculator(expr):
if len(expr) <= 0 or not isinstance(expr, str):
return "error"
expr = expr.strip()
if expr[0] != "-":
newNumber, newOpr, oprPos = getNextNumber(expr, 0)
else:
newNumber, newOpr, oprPos = getNextNumber(expr, 1)
newNumber *= -1
if newNumber is None:
return "error"
elif newOpr is None:
return newNumber
elif newOpr == "+" or newOpr == "-":
mode = "add"
addResult = newNumber
mulResult = None
expResult = None
elif newOpr == "*" or newOpr == "/":
mode = "mul"
addResult = 0
mulResult = newNumber
expResult = None
elif newOpr == "^":
mode = "exp"
expResult = newNumber
addResult = 0
mulResult = None
pos = oprPos + 1
opr = newOpr
oldopr = None
while True:
newNumber, newOpr, oprPos = getNextNumber(expr, pos)
if newNumber is None:
return "input error: line B in calculator"
elif newOpr is None:
if mode == 'add':
if opr == '*':
return exeOpr(addResult, oldopr, mulResult * newNumber)
elif opr == '/':
return exeOpr(addResult, oldopr, mulResult / newNumber)
else:
return exeOpr(addResult, opr, newNumber)
elif mode == 'mul':
if expResult == None:
expResult = 0
if mulResult == None:
mulResult = 0
return addResult + exeOpr(mulResult, opr, newNumber)
elif mode == "exp":
if expResult < 0:
expResult = exeOpr(expResult, opr, newNumber)
if expResult > 0:
expResult = -1 * expResult
else:
expResult = exeOpr(expResult, opr, newNumber)
if mulResult != 0 and (oldopr == '*' or oldopr == '/'):
mulResult = exeOpr(mulResult, oldopr, expResult)
expResult = 0
elif newOpr == '+' or newOpr == '-':
if expResult == None:
expResult = 0
if mulResult == None:
mulResult = 0
if mode == 'add':
addResult = exeOpr(addResult, opr, newNumber)
mulResult = 0
expResult = 0
elif mode == 'mul':
addResult += exeOpr(mulResult, opr, newNumber)
mulResult = 0
expResult = 0
elif mode == 'exp':
if expResult < 0:
expResult = exeOpr(expResult, opr, newNumber)
if expResult > 0:
expResult = -1 * expResult
addResult += expResult
else:
addResult += exeOpr(expResult, opr, newNumber)
if oldopr == '*' or oldopr == '/':
expResult = exeOpr(expResult, opr, newNumber)
mulResult = exeOpr(mulResult, oldopr, expResult)
addResult += mulResult
mulResult = 0
expResult = 0
mode = 'add'
elif newOpr == "*" or newOpr == "/":
if mode == 'add':
if opr == '-':
oldopr = '-'
mulResult = -newNumber # <====== THIS IS THE PLACE I CHANGED
elif opr == '+':
# print('here1')
oldopr = '+'
mulResult = newNumber
mode = 'mul'
else:
mulResult = newNumber
elif mode == 'mul':
mulResult = exeOpr(mulResult, opr, newNumber)
elif mode == 'exp':
if expResult < 0:
expResult = exeOpr(expResult, opr, newNumber)
if expResult > 0:
expResult = -1 * expResult
else:
expResult = exeOpr(expResult, opr, newNumber)
if mulResult != 0 and (oldopr == '*' or oldopr == '/'):
mulResult = exeOpr(mulResult, oldopr, expResult)
expResult = 0
else:
mulResult = expResult
expResult = 0
mode = 'mul'
elif newOpr == '^':
if mode == 'add':
if expResult == None:
expResult = 0
if mulResult == None:
mulResult = 0
if opr == '-':
expResult = -newNumber
else:
expResult = newNumber
oldopr = opr
elif mode == 'mul':
expResult = newNumber
oldopr = opr
mode = 'exp'
if oprPos == None:
break
pos = oprPos + 1
opr = newOpr
if mulResult == None:
mulResult = 0
if expResult == None:
expResult = 0
return addResult + mulResult + expResult
x = calculator('-5 + 60 / 3^3 * 4 - 2 * 4^2')
print(x)