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]:
['100', '*', '(', '2', '+', '12', ')', '-', '(', '20', '/', '3', ')', '*', '2']

In [27]:
5 // -2


Out[27]:
-3

In [32]:
-5 // -2


Out[32]:
2

In [29]:
import math
from __future__ import print_function, division, absolute_import, unicode_literals

In [30]:
math.ceil(5 / -2)


Out[30]:
-2.0

In [33]:
math.ceil(-5 / -2)


Out[33]:
3.0

In [31]:
math.floor(5 / -2)


Out[31]:
-3.0

In [34]:
math.floor(-5 / -2)


Out[34]:
2.0

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]:
[1388]

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]:
[1388]