2017-07-20 79 views
0

我试图找出一个简单的python计算器使用栈,它只适用于负数是第一种情况,当没有负数时,但是当出现这种情况时?为4 * -2例如,它给出了一个错误(我的目光都集中在getNextNumber和ISNUMBER和findNextOpr有没有办法解决这个问题下面的代码:Python计算器,特别是getNextNumber函数无法正常工作

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

这是一个预期的问题要克服这个,电子计算器通常使用减号负号单独标志(这在Python中是一样的,导致你的问题)。可以通过为这些创建一个操作符类来应用它,为它们指定特定的目的。

或者,可以强制paranthesis的正确用法是取输入时,或预检查输入,并将其转换,而不会打扰用户,使之成为计算机可用的格式(添加paranthesis或任何)。

+0

我创建了一个函数来确定是否存在括号,但主要问题是使用getNextNumber函数,因为findNextOpr函数向getNextNumber提供了一个零。 – ARomedtbf