1+ """
2+ Contributed by izanbf1803.
3+
4+ Example:
5+ -------------------------------------------------------------------------------------------------
6+ Code:
7+ | exp = "2452 * (3 * 6.5 + 1) * 6 / 235"
8+ | print("Expression:", exp)
9+ | print("Parsed expression:", mp.parse(exp))
10+ | print("Evaluation result:", mp.evaluate(exp))
11+
12+ Output:
13+ | Expression: 2452 * (3 * 6 + 1) * 6 / 235
14+ | Parsed expression: ['2452', '*', '(', '3', '*', '6', '+', '1', ')', '*', '6', '/', '235']
15+ | Evaluation result: 1189.4808510638297
16+ -------------------------------------------------------------------------------------------------
17+ """
18+
19+ from collections import deque
20+ import re
21+
22+ numeric_value = re .compile ('\d+(\.\d+)?' )
23+
24+ __operators__ = "+-/*"
25+ __parenthesis__ = "()"
26+ __priority__ = {
27+ '+' : 0 ,
28+ '-' : 0 ,
29+ '*' : 1 ,
30+ '/' : 1 ,
31+ }
32+
33+ def is_operator (token ):
34+ """
35+ Check if token it's a operator
36+
37+ token Char: Token
38+ """
39+ return token in __operators__
40+
41+ def higher_priority (op1 , op2 ):
42+ """
43+ Check if op1 have higher priority than op2
44+
45+ op1 Char: Operation Token 1
46+ op2 Char: Operation Token 2
47+ """
48+ return __priority__ [op1 ] >= __priority__ [op2 ]
49+
50+ def calc (n2 , n1 , operator ):
51+ """
52+ Calculate operation result
53+
54+ n2 Number: Number 2
55+ n1 Number: Number 1
56+ operator Char: Operation to calculate
57+ """
58+ if operator == '-' : return n1 - n2
59+ elif operator == '+' : return n1 + n2
60+ elif operator == '*' : return n1 * n2
61+ elif operator == '/' : return n1 / n2
62+ return 0
63+
64+ def apply_operation (op_stack , out_stack ):
65+ """
66+ Apply operation to the first 2 items of the output queue
67+
68+ op_stack Deque (reference)
69+ out_stack Deque (reference)
70+ """
71+ out_stack .append (calc (out_stack .pop (), out_stack .pop (), op_stack .pop ()))
72+
73+ def parse (expression ):
74+ """
75+ Return array of parsed tokens in the expression
76+
77+ expression String: Math expression to parse in infix notation
78+ """
79+ result = []
80+ current = ""
81+ for i in expression :
82+ if i .isdigit () or i == '.' :
83+ current += i
84+ else :
85+ if len (current ) > 0 :
86+ result .append (current )
87+ current = ""
88+ if i != ' ' :
89+ result .append (i )
90+ if len (current ) > 0 :
91+ result .append (current )
92+ return result
93+
94+ def evaluate (expression ):
95+ """
96+ Calculate result of expression
97+
98+ expression String: The expression
99+ type Type (optional): Number type [int, float]
100+ """
101+ op_stack = deque () # operator stack
102+ out_stack = deque () # output stack (values)
103+ for token in parse (expression ):
104+ if numeric_value .match (token ):
105+ out_stack .append (float (token ))
106+ elif token == '(' :
107+ op_stack .append (token )
108+ elif token == ')' :
109+ while len (op_stack ) > 0 and op_stack [- 1 ] != '(' :
110+ apply_operation (op_stack , out_stack )
111+ op_stack .pop () # Remove remaining '('
112+ else : # is_operator(token)
113+ while len (op_stack ) > 0 and is_operator (op_stack [- 1 ]) and higher_priority (op_stack [- 1 ], token ):
114+ apply_operation (op_stack , out_stack )
115+ op_stack .append (token )
116+
117+ while len (op_stack ) > 0 :
118+ apply_operation (op_stack , out_stack )
119+
120+ return out_stack [- 1 ]
0 commit comments