In [4]:
import re
In [22]:
formula = "100 *(2+ 12)-(20 /3)*2"
In [23]:
ops_re = "([-+*/()])"
tokens = [t for t in (x.strip() for x in re.split(ops_re, formula)) if len(t) > 0]
In [24]:
tokens
Out[24]:
In [27]:
5 // -2
Out[27]:
In [32]:
-5 // -2
Out[32]:
In [29]:
import math
from __future__ import print_function, division, absolute_import, unicode_literals
In [30]:
math.ceil(5 / -2)
Out[30]:
In [33]:
math.ceil(-5 / -2)
Out[33]:
In [31]:
math.floor(5 / -2)
Out[31]:
In [34]:
math.floor(-5 / -2)
Out[34]:
In [36]:
def add(a, b):
return a + b
def minus(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
return int(a / b)
op_func = {
'+': add,
'-': minus,
'*': multiply,
'/': divide
}
op_prior = {
'+': 0,
'-': 0,
'*': 1,
'/': 1
}
In [63]:
num_stack = []
op_stack = []
for token in tokens:
try:
number = int(token)
num_stack.append(number)
except ValueError: # here is operators
if token == '(':
op_stack.append(token)
elif token == ')':
op = op_stack.pop()
while op != '(':
num2 = num_stack.pop()
num1 = num_stack.pop()
num_stack.append(op_func[op](num1, num2))
op = op_stack.pop()
else:
try:
op = op_stack.pop()
if op == '(':
op_stack.append(op)
else:
if op_prior[token] > op_prior[op]:
op_stack.append(op)
else:
num2 = num_stack.pop()
num1 = num_stack.pop()
num_stack.append(op_func[op](num1, num2))
except IndexError:
pass
op_stack.append(token)
while len(op_stack) > 0:
op = op_stack.pop()
num2 = num_stack.pop()
num1 = num_stack.pop()
num_stack.append(op_func[op](num1, num2))
In [64]:
num_stack
Out[64]:
In [65]:
op_stack
Out[65]:
In [66]:
num_stack = []
op_stack = []
def process(op, num_stack=num_stack, op_func=op_func): # go with one operator
num2 = num_stack.pop()
num1 = num_stack.pop()
num_stack.append(op_func[op](num1, num2))
for token in tokens:
try:
number = int(token)
num_stack.append(number)
except ValueError: # here is operators
if token == '(':
op_stack.append(token)
elif token == ')': # calc until the matching left param
op = op_stack.pop()
while op != '(':
process(op)
op = op_stack.pop()
else: # normal +, -, * and /
try:
op = op_stack.pop()
if op == '(': # don't touch left param
op_stack.append(op)
else:
if op_prior[token] > op_prior[op]:
op_stack.append(op)
else:
process(op)
except IndexError:
pass
op_stack.append(token)
while len(op_stack) > 0:
op = op_stack.pop()
process(op)
In [67]:
num_stack
Out[67]: