2015-06-16 44 views
2

複雜的表達式引起我已經實現了調度場算法因爲在這裏可以看到計算器錯誤

#!/usr/bin/env python 

import sys 
import string 
import operator 
import signal 

class InvalidStackError(Exception): pass 
class BadParenError(Exception): pass 

def hook_ctrl_c(signal, frame): 
    print "" 
    sys.exit(0) 

signal.signal(signal.SIGINT, hook_ctrl_c) 

ops = { 
    "*" : [operator.mul, 3, "left"], 
    "x" : [operator.mul, 3, "left"], 
    "/" : [operator.div, 3, "left"], 
    "+" : [operator.add, 2, "left"], 
    "-" : [operator.sub, 2, "left"], 
    "^" : [operator.pow, 4, "right"], 
    "(" : [None, 5, "neither"], 
    ")" : [None, 5, "neither"] 
} 

def parse(raw): 
    return raw.split() 

def compile_to_rpn(tokens): 
    operator_stack = [] 
    rpn_code = [] 

    for token in tokens: 
     try: 
      current_number = int(token) 
      rpn_code.append(current_number) 

     except ValueError: 
      if token == "(": 
       operator_stack.append(token) 

      elif token == ")": 
       try: 
        while True: 
         current_operator = operator_stack.pop() 

         if current_operator == "(": 
          break 

         rpn_code.append(current_operator) 

       except IndexError: 
        print "(error) mismatched parens" 

      elif token in ops: 
       if len(operator_stack) > 0 and ((ops[token][2] == "left" and ops[token][1] <= ops[operator_stack[-1]][1]) or (ops[token][2] == "right" and ops[token][1] < ops[operator_stack[-1]][1])): 
        operator = operator_stack.pop() 

        if operator != "(": 
         rpn_code.append(operator_stack.pop()) 

        else: 
         operator_stack.append("(") 

       operator_stack.append(token) 
    try: 
     while len(operator_stack) != 0: 
      current_operator = operator_stack.pop() 

      if current_operator in ["(", ")"]: 
       raise BadParenError 

      rpn_code.append(current_operator) 

    except BadParenError: 
     print "(error) mismatched parens" 

    return rpn_code 

current_token = None 

while True: 
    try: 
     tokens = parse(raw_input("-> ")) 
     stack = [] 

     if tokens == ["quit"]: 
      sys.exit(0) 

     tokens = compile_to_rpn(tokens) 

     for token in tokens: 
      current_token = token 

      if token not in ops: 
       stack.append(int(token)) 

      else: 
       rhs, lhs = stack.pop(), stack.pop() 
       stack.append(ops[token][0](lhs, rhs)) 

     if len(stack) > 1: 
      raise InvalidStackError 

     print "Result: %s\n" % stack[0] 

    except ValueError: 
     print "(error) token {%s} is a not a number or operator\n" % current_token 

    except IndexError: 
     print "(error) expression has insufficient number of values\n" 

    except InvalidStackError: 
     print "(error) too many values\n" 

它工作正常進行簡單的諸如「3 + 4」,但如果我進入複雜的事情,發生這種情況:

$ ./rpn.py

- > 4 - 5 * 6 + 3^2

(error)太多值

在此先感謝,我感謝任何幫助!

回答

0

至少有一個問題,你的代碼是在這裏:

  if len(operator_stack) > 0 and ((ops[token][2] == "left" and ops[token][1] <= ops[operator_stack[-1]][1]) or (ops[token][2] == "right" and ops[token][1] < ops[operator_stack[-1]][1])): 
       operator = operator_stack.pop() 

       if operator != "(": 
        rpn_code.append(operator_stack.pop()) 

您從operator_stack彈出,然後再做追加到rpn_code時。這會觸發你的一個例外。與

    rpn_code.append(operator) 

而像5 * 6 + 4表達式將正常工作,更換這個片段的最後一行。不幸的是,這不是您代碼中的唯一錯誤,因爲您提供的示例沒有正確評估。也許這是因爲你的代碼的另一個問題:做算法的這部分(維基百科)時:

如果令牌是一個運營商,O1,則:

while there is an operator token, o2, at the top of the operator stack, and either 

     o1 is left-associative and its precedence is less than or equal to that of o2, or 
     o1 is right associative, and has precedence less than that of o2, 

    then pop o2 off the operator stack, onto the output queue; 

    push o1 onto the operator stack. 

你」只重新執行一次,而不是隻要條件滿足。

+0

哦,我現在可以看到。謝謝! – DTSCode