我尝试使用堆栈计算出一个简单的python计算器,它仅适用于负数是第一个且没有负数的情况,但是当出现诸如4 * -2等情况时,它给出了一个错误(我的眼睛在getNextNumber和isNumber和findNextOpr。有没有办法解决这个问题?这里的代码是:
import pdb
class Stack:
def __init__(self):
self.container = []
def isEmpty(self):
return self.size() == 0
def push(self, item):
self.container.append(item)
def pop(self):
return self.container.pop()
def size(self):
return len(self.container)
class stack:
class node:
def __init__(self, value, nextNode):
self.value = value
self.nextNode = nextNode
def __init__(self):
self.top = None
self.last = None
self.size = 0
def __len__(self):
return self.size
def isEmpty(self):
return self.size == 0
def push(self, value):
if self.size == 0:
self.top = self.last = self.node(value, None)
else:
newNode = self.node(value, None)
newNode.nextNode = self.top
self.top = newNode
self.size += 1
def pop(self):
if self.size == 0:
return 'Error: stack.pop'
elif self.size == 1:
value = self.top.value
self.top = self.last = None
self.size -= 1
return value
else:
value = self.top.value
self.top = self.top.nextNode
self.size -= 1
return value
def findNextOpr(s):
if len(s) <= 0 or not isinstance(s, str):
print('Type mismatch error: findNextOpr')
return 'Type mismatch error: findNextOpr'
for n in range(len(s)):
if ord(s[n]) == 42 or ord(s[n]) == 43 or ord(s[n]) == 45 or ord(s[n]) == 47 or ord(s[n]) == 94:
return n
else:
continue
return -1
def isNumber(s):
if len(s) == 0 or not isinstance(s, str):
print('Type mismatch error: isNumber')
return 'Type mismatch error: isNumber'
try:
float(s)
return True
except:
return False
def getNextNumber(expr, pos):
#pdb.set_trace()
if len(expr) == 0 or not isinstance(expr, str) or pos < 0 or pos >= len(expr) or not isinstance(pos, int):
print('Type mismatch error: getNextNumber')
return None, None, 'Type mismatch error: getNextNumber'
m = findNextOpr(expr[pos:])
if m != -1:
opr = expr[m]
if isNumber(expr[pos: m + pos]) is True:
return float(expr[pos: m + pos]), expr[pos + m], m
elif isNumber(expr[pos:m+pos]) is False:
if expr[m+1] == '-':
pos = m+1
num=getNextNumber(expr,pos)
return -float(num),None,None
else:
return None, None, None
elif m == -1:
if isNumber(expr[pos:]) is True:
return float(expr[pos:]), None, None
else:
return None, None, None
def exeOpr(num1, opr, num2):
if opr == '+':
return num1 + num2
elif opr == '-':
return num1 - num2
elif opr == '*':
return num1 * num2
elif opr == '/':
if num2 == 0:
print('Zero division error: exeOpr')
return 'Zero division error: exeOpr'
else:
return num1 / num2
elif opr == '^':
return num1 ** num2
else:
print('Fatal internal error in exeOpr')
return 'Fatal internal error in exeOpr'
def _calc(expr):
if not isinstance(expr, str) or len(expr) <= 0:
print('Argument error: Line A in eval_expr')
return 'Argument error: Line A in eval_expr'
newNumber, newOpr, oprPos = getNextNumber(expr, 0)
if newNumber is None:
print('Input formula error: Line B in eval_expr')
return 'Input formula error: Line B in eval_expr'
elif newOpr is None:
return newNumber
elif newOpr == '+' or newOpr == '-':
mode = 'add'
addResult = newNumber
mulResult = 1
expResult = 0
elif newOpr == '*' or newOpr == '/':
mode = 'mul'
addResult = 0
mulResult = newNumber
expResult = 1
elif newOpr == '^':
mode = 'exp'
addResult = 0
mulResult = 1
expResult = newNumber
pos = oprPos + 1
opr = newOpr
while True:
nextNumber, newOpr, oprPos = getNextNumber(expr, pos)
if nextNumber is None or pos >= len(expr):
print('Input formula error: Line C in calc')
return 'Input formula error: Line C in calc'
elif newOpr is None:
if mode == 'add':
return exeOpr(addResult, opr, nextNumber)
elif mode == 'mul':
return exeOpr(mulResult, opr, nextNumber) + addResult
elif mode == 'exp':
return exeOpr(expResult, opr, nextNumber) * mulResult + addResult
oprPos += pos
pos = oprPos + 1
if mode == 'add':
if newOpr == '+' or newOpr == '-':
addResult = exeOpr(addResult, opr, nextNumber)
mode = 'add'
elif newOpr == '*' or newOpr == '/':
if opr == '+':
mulResult = nextNumber
elif opr == '-':
mulResult = -nextNumber
mode = 'mul'
elif newOpr == '^':
if opr == '+':
expResult = nextNumber
elif opr == '-':
expResult = - nextNumber
mode = 'exp'
elif mode == 'mul':
if newOpr == '*' or newOpr == '/':
mulResult = exeOpr(mulResult, opr, nextNumber)
mode = 'mul'
elif newOpr == '+' or newOpr == '-':
addResult += exeOpr(mulResult, opr, nextNumber)
elif newOpr == '^':
if opr == '*':
expResult = 1 / nextNumber
mode = 'exp'
elif mode == 'exp':
if newOpr == '^':
expResult = exeOpr(expResult, opr, nextNumber)
mode = 'exp'
elif newOpr == '+' or newOpr == '-':
addResult = exeOpr(expResult, opr, nextNumber) * mulResult + addResult
mode = 'add'
elif newOpr == '*' or newOpr == '/':
mulResult = exeOpr(expResult, opr, nextNumber) * mulResult
mode = 'mul'
opr = newOpr
def icheck(expr):
d = None
if expr[0] == '-':
expr = '0' + expr
for i in range(len(expr)):
if expr[i] == '(':
d = i
elif expr[i] == '':
continue
elif d is not None and expr[i] == '-':
for j in range(i + 1, len(expr)):
if expr[j] == '':
continue
else:
expr = expr[0: d + 1] + '0' + expr[d+1:]
d = None
break
else:
d = None
return expr
def pcheck(expr):
expr = expr.replace(' ', '')
per = Stack()
for i in range(len(expr)):
if expr[i] == '(':
if i != 0 and isNumber(expr[i - 1]) == True:
print('Omitting Operator')
return False
per.push(i)
elif expr[i] == ')':
if i != (len(expr) - 1) and isNumber(expr[i + 1]) == True:
print('Omitting Operator')
return False
try:
per.pop()
except IndexError:
print('Parenthesis are unbalanced')
return False
return per.isEmpty()
def calc(e, u=None):
if len(e) == 0:
return 'Empty String'
e = e.replace(' ', '')
if u is None:
e = icheck(e)
tf = pcheck(e)
if tf is False:
return IndexError
st = Stack()
b = None
for i in range(len(e)):
pos = i
if e[i] == '(':
st.push(i)
elif e[i] == ')':
b = st.pop()
c = i
break
if b is None:
return _calc(e)
if st.size() == 0 and (pos == len(e) - 1):
res = _calc(e[b+1:c])
if len(e) > c:
e = e[:b] + str(res) + e[c + 1:]
else:
e = e[:b] + str(res)
return _calc(e)
else:
res = _calc(e[b + 1: c])
e = e[:b] + str(res) + e[c + 1:]
return calc(e, u=1)
print(calc('2.0*-2+5'))
print(calc('-2.0+1'))
print(calc('4*-2'))
print(calc('2+3*(-2 +(-3)*(5^2-2*3^(-2))*(-4))*(2/8+2*(3–1/3))-2/3^2'))
print(calc('1+3-2/30^2/5-1*5*3*4/3-1^2/6/7/8+3-1/2^2*3/2+3+1^2^2+3/3^2'))
答案 0 :(得分:0)
这是一个预期的问题。为了解决这个问题,电子计算器通常单独使用负和负符号(这在Python中是相同的,导致您的问题)。您可以通过为这些创建运算符类来应用它,为它们指定特定目的。
或者,您可以在输入时强制正确使用paranthesis,或预先检查输入并转换它而不打扰用户,使其成为计算机可用格式(添加paranthesis或无论如何)。