chapter 6: Calculator¶
6.1 math parser¶
Contributed by izanbf1803.
Example:¶
- Code:
exp = "2452 * (3 * 6.5 + 1) * 6 / 235"print("Expression:", exp)print("Parsed expression:", mp.parse(exp))print("Evaluation result:", mp.evaluate(exp))- Output:
Expression: 2452 * (3 * 6 + 1) * 6 / 235Parsed expression: ['2452', '*', '(', '3', '*', '6', '+', '1', ')', '*', '6', '/', '235']Evaluation result: 1189.4808510638297
Now added '^' operator for exponents. (by @goswami-rahul)
from collections import deque
import re
numeric_value = re.compile('\d+(\.\d+)?')
__operators__ = "+-/*^"
__parenthesis__ = "()"
__priority__ = {
'+': 0,
'-': 0,
'*': 1,
'/': 1,
'^': 2
}
def is_operator(token):
"""
Check if token it's a operator
token Char: Token
"""
return token in __operators__
def higher_priority(op1, op2):
"""
Check if op1 have higher priority than op2
op1 Char: Operation Token 1
op2 Char: Operation Token 2
"""
return __priority__[op1] >= __priority__[op2]
def calc(n2, n1, operator):
"""
Calculate operation result
n2 Number: Number 2
n1 Number: Number 1
operator Char: Operation to calculate
"""
if operator == '-': return n1 - n2
elif operator == '+': return n1 + n2
elif operator == '*': return n1 * n2
elif operator == '/': return n1 / n2
elif operator == '^': return n1 ** n2
return 0
def apply_operation(op_stack, out_stack):
"""
Apply operation to the first 2 items of the output queue
op_stack Deque (reference)
out_stack Deque (reference)
"""
out_stack.append(calc(out_stack.pop(), out_stack.pop(), op_stack.pop()))
def parse(expression):
"""
Return array of parsed tokens in the expression
expression String: Math expression to parse in infix notation
"""
result = []
current = ""
for i in expression:
if i.isdigit() or i == '.':
current += i
else:
if len(current) > 0:
result.append(current)
current = ""
if i in __operators__ or i in __parenthesis__:
result.append(i)
else:
raise Exception("invalid syntax " + i)
if len(current) > 0:
result.append(current)
return result
def evaluate(expression):
"""
Calculate result of expression
expression String: The expression
type Type (optional): Number type [int, float]
"""
op_stack = deque() # operator stack
out_stack = deque() # output stack (values)
tokens = parse(expression) # calls the function only once!
for token in tokens:
if numeric_value.match(token):
out_stack.append(float(token))
elif token == '(':
op_stack.append(token)
elif token == ')':
while len(op_stack) > 0 and op_stack[-1] != '(':
apply_operation(op_stack, out_stack)
op_stack.pop() # Remove remaining '('
else: # is_operator(token)
while len(op_stack) > 0 and is_operator(op_stack[-1]) and higher_priority(op_stack[-1], token):
apply_operation(op_stack, out_stack)
op_stack.append(token)
while len(op_stack) > 0:
apply_operation(op_stack, out_stack)
return out_stack[-1]
def main():
"""
simple user-interface
"""
print("\t\tCalculator\n\n")
while True:
user_input = input("expression or exit: ")
if user_input == "exit":
break
try:
print("The result is {0}".format(evaluate(user_input)))
except Exception:
print("invalid syntax!")
user_input = input("expression or exit: ")
print("program end")
if __name__ == "__main__":
main()