2012-12-04 160 views
1
import string 

# Strength of operations: 
# -> [] (brackets) 
# 6 -> ~ (negative) 
# 5 -> @, $, & (average, maximum, minimum) 
# 4 -> %, ! (modulo, factorial) 
# 3 ->^(power) 
# 2 -> *,/(multiplication, division) 
# 1 -> +, - (addition, subtraction) 

def BinaryOperation(exp, idx): 
    """ Gets an expression and an index of an operator and returns a tuple with (first_value, operator, second_value). """ 
    first_value = 0 
    second_value = 0 

    #Get first value 
    idx2 = idx -1 
    if idx2 == 0: 
     first_value = exp[idx2:idx] 

    else: 
     while (idx2 > 0) and (exp[idx2] in string.digits): 
      idx2 -=1 

     if (exp[idx2] in ("-")) or (exp[idx2] in string.digits):#-5*3 
      first_value = exp[idx2:idx] 
     else:#%5*3 
      first_value = exp[idx2+1:idx] 

    #Get second value 
    idx2 = idx +1 
    if exp[idx+1] not in string.digits: #If there is something like 1*+5, second_sign will be +. 
     idx2 += 1 #idx2 will begin from the char after the sign. 

    while (idx2 < len(exp)) and (exp[idx2] in string.digits): 
     idx2 += 1 

    second_value = exp[idx+1:idx2] 

    return (first_value, exp[idx], second_value) 

def UnaryOperation(exp, idx): 
    """ Gets an expression and an index of an operator and returns a tuple with (operator, value). """ 
    #Get value 
    idx2 = idx+1 
    if exp[idx+1] not in string.digits: #If there is something like ~-5, second_sign will be -. 
     idx2 += 1 #idx2 will begin from the char after the sign. 
    while (idx2 < len(exp)) and (exp[idx2] in string.digits): 
     idx2 +=1 

    return (exp[idx], exp[idx+1:idx2]) 

def Brackets(exp): 
    idx = 0 
    while idx < len(exp): 
     if exp[idx] == "[": 
      #Brackets 
      close_bracket = exp.find("]") 
      if close_bracket == -1: 
       raise Exception("Missing closing bracket.") 

      exp_brackets = exp[idx+1:close_bracket] 

      value = str(solve(exp_brackets)) 

      exp = exp.replace("[" + exp_brackets + "]", value) 
      idx = 0 #The len has been changed, scan again. 

     idx += 1 

    return Level6(exp) 

def Level6(exp): 
    idx = 0 
    while idx < len(exp): 
     if exp[idx] in ("~"): 
      #Negative 
      sub_exp = UnaryOperation(exp, idx) 
      value = ~int(sub_exp[1]) 

      value = str(value) 

      exp = exp.replace(''.join(sub_exp), value) 
      idx = 0 #The len has been changed, scan again. 

     idx += 1 
    return Level5(exp) 

def Level5(exp): 
    idx = 0 
    while idx < len(exp): 
     if exp[idx] in ("@", "$", "&"): 
      #Average, Maximum and Minimum 
      sub_exp = BinaryOperation(exp, idx) 
      first_value = int(sub_exp[0]) 
      second_value = int(sub_exp[2]) 
      if sub_exp[1] == "@": 
       value = (first_value + second_value)/2 
      if sub_exp[1] == "$": 
       value = first_value if first_value > second_value else second_value 
      if sub_exp[1] == "&": 
       value = first_value if first_value < second_value else second_value 

      value = str(value) 

      exp = exp.replace(''.join(sub_exp), value) 
      idx = 0 #The len has been changed, scan again. 

     idx += 1 

    return Level4(exp) 

def Level4(exp): 
    idx = 0 
    while idx < len(exp): 
     if exp[idx] in ("%","!"): 
      #Modulo and Factorial 
      if exp[idx] == "%": 
       sub_exp = BinaryOperation(exp, idx) 
       value = int(sub_exp[0]) % int(sub_exp[2]) 
      if exp[idx] == "!": 
       sub_exp = UnaryOperation(exp, idx) 
       value = reduce(lambda x,y:x*y, range(1, int(sub_exp[1])+1)) 


      value = str(value) 

      exp = exp.replace(''.join(sub_exp), value) 
      idx = 0 #The len has been changed, scan again. 

     idx += 1 

    return Level3(exp) 

def Level3(exp): 
    idx = 0 
    while idx < len(exp): 
     if exp[idx] in ("^"): 
      #Power 
      sub_exp = BinaryOperation(exp, idx) 
      value = int(sub_exp[0]) ** int(sub_exp[2]) 

      value = str(value) 

      exp = exp.replace(''.join(sub_exp), value) 
      idx = 0 #The len has been changed, scan again. 

     idx += 1 

    return Level2(exp) 


def Level2(exp): 
    idx = 0 
    while idx < len(exp): 
     if exp[idx] in ("*", "/"): 
      #Multiplication and Division 
      sub_exp = BinaryOperation(exp, idx) 
      if sub_exp[1] == "*": 
       value = int(sub_exp[0]) * int(sub_exp[2]) 
      if sub_exp[1] == "/": 
       value = int(sub_exp[0])/int(sub_exp[2]) 

      value = str(value) 

      exp = exp.replace(''.join(sub_exp), value) 
      idx = 0 #The len has been changed, scan again. 

     idx += 1 

    return Level1(exp) 

def Level1(exp): 
    idx = 0 
    while idx < len(exp): 
     if (exp[idx] in ("+", "-")) and (idx != 0): 
      #Addition and Subtraction 
      sub_exp = BinaryOperation(exp, idx) 
      if sub_exp[1] == "+": 
       value = int(sub_exp[0]) + int(sub_exp[2]) 
      if sub_exp[1] == "-": 
       value = int(sub_exp[0]) - int(sub_exp[2]) 

      value = str(value) 

      exp = exp.replace(''.join(sub_exp), value) 
      idx = 0 #The len has been changed, scan again. 

     idx += 1 

    return exp 

def solve(exp): 
    exp = Brackets(exp) 
    return float(exp) if "." in exp else int(exp) 

def remove_whitespace(exp): 
    """ Gets a string and removes all whitespaces and tabs """ 
    exp = exp.replace(" ", "") 
    exp = exp.replace("\t", "") 
    return exp 

while True: 
    exp = raw_input("") 
    exp = remove_whitespace(exp) 
    print solve(exp) 

我已经写了很多努力后,这个程序,我想知道该解决方案的效率,如果它是整洁。计算器解析用户输入

所以我的问题是,这个程序有多简单,有没有更好的方法来重写它?

+2

这是不是可以更适合http://codereview.stackexchange.com/? – NPE

+0

@NPE谢谢,我也会在那里发帖。 – Lior

回答

1

只是为了这一点。

>>> eval(raw_input("input calculation: ")) 
input calculation: 1+1 
2 
>>> eval(raw_input("input calculation: ")) 
input calculation: (6*4^2) 
26 
>>> eval(raw_input("input calculation: ")) 
input calculation: (3/2.3)*4 
5.2173913043478262 

一个无辜的程序,你可以使用eval

,但你真的不应该永远使用它。它唯一真正的用途是混淆人们,如果你自己编写程序并决定你想要一个计算器,那么它会成为一个有趣的新奇事物。

有很多方法来编写计算器功能。

尝试一些其他的答案:

Python creating a calculator

Basic calculator program in python

python calculator program

0
again = True 
answer = "" 
while again is True: 
    try: 
     expression = raw_input("Enter your expression: ") 
     found = False 
     oper = -1 
     operator1 = 0 
     operator2 = 0 
     while found==False: 
      if (expression.find("+")>0 and expression.find("+")<len(expression)-1): 
       found = True 
       oper = expression.find("+") 
       operator1 = float(expression[:oper]) 
       operator2 = float(expression[oper+1:]) 
       print "{} + {} = {}".format(operator1,operator2,operator1+operator2) 
      elif(expression.find("-")>0 and expression.find("-")<len(expression)-1): 
       found = True 
       oper = expression.find("-") 
       operator1 = float(expression[:oper]) 
       operator2 = float(expression[oper+1:]) 
       print "{} - {} = {}".format(operator1,operator2,operator1-operator2) 
      elif(expression.find("*")>0 and expression.find("*")<len(expression)-1): 
       found = True 
       oper = expression.find("*") 
       operator1 = float(expression[:oper]) 
       operator2 = float(expression[oper+1:]) 
       print "{} * {} = {}".format(operator1,operator2,operator1*operator2) 
      elif(expression.find("/")>0 and expression.find("/")<len(expression)-1): 
       found = True 
       oper = expression.find("/") 
       operator1 = float(expression[:oper]) 
       operator2 = float(expression[oper+1:]) 
       print "{}/{} = {}".format(operator1,operator2,operator1/operator2) 
      else: 
       oper = -1 
       found = False 
       print "Incorrect expression, please try again" 
       break 
      again = False 
      answer = raw_input("Try again?: ") 
      if(answer == "y" or answer=="yes" or answer =="Y" or answer == "YES"): 
       again = True 
      else: 
       again = False 
       print "Thank you for playing! See you next time." 
       break 

    except: 
     print "Failed, check your expression and try again"