class Calculator: def __init__(self): self.functions = { 'EXP': Function(numpy.exp), 'LOG': Function(numpy.log), 'SIN': Function(numpy.sin), 'COS': Function(numpy.cos), 'SQRT': Function(numpy.sqrt) } self.operators = { 'ADD': Operator(numpy.add, 0), 'PLUS': Operator(numpy.add, 0), 'MULTIPLY': Operator(numpy.multiply, 1), 'TIMES': Operator(numpy.multiply, 1), 'DIVIDE': Operator(numpy.divide, 1), 'SUBTRACT': Operator(numpy.subtract, 0), 'MINUS': Operator(numpy.subtract, 0) } self.output_queue = Queue() self.input_queue = Queue() def evaluate(self): """ ... """ stack = Stack() for i in range(self.output_queue.size()): element = self.output_queue.pop() if isinstance(element, numbers.Number): stack.push(element) elif isinstance(element, Function): num = stack.pop() calculated_value = element.execute(num) stack.push(calculated_value) elif isinstance(element, Operator): num1 = stack.pop() num2 = stack.pop() calculated_value = element.execute(num2, num1) stack.push(calculated_value) else: raise Exception("Wrong type in the output_queue") if stack.size() != 1: raise Exception("Stack should be of size 1.") return stack.pop() def convert_queue_to_rpn(self): """ ... """ operator_stack = Stack() for i in range(self.input_queue.size()): element = self.input_queue.pop() if isinstance(element, numbers.Number): self.output_queue.push(element) elif isinstance(element, Function): operator_stack.push(element) elif element == "(": operator_stack.push(element) elif element == ")": while operator_stack.peek() != "(": self.output_queue.push(operator_stack.pop()) operator_stack.pop() elif isinstance(element, Operator): while operator_stack.size() != 0: next_element = operator_stack.peek() if isinstance(next_element, Operator): if next_element.strength < element.strength: break elif next_element == "(": break self.output_queue.push(operator_stack.pop()) operator_stack.push(element) else: raise Exception("Wrong type in input queue") for i in range(operator_stack.size()): self.output_queue.push(operator_stack.pop()) def text_parser(self, text): """ parse text with regex """ text = text.replace(" ", "").upper() # Make match strings for regex functions = "|".join(["^" + func for func in self.functions.keys()]) operators = "|".join(["^" + func for func in self.operators.keys()]) parenthesis = "^[()]" nums = "^[-1234567890]+" while text != "": check_num = re.search(nums, text) # Check if number if check_num is not None: matched_num = check_num.__getitem__(0) self.input_queue.push(float(matched_num)) text = text[len(matched_num)::] continue check_par = re.search(parenthesis, text) # Check if parenthesis if check_par is not None: matched_par = check_par.__getitem__(0) self.input_queue.push(matched_par) text = text[1::] continue check_op = re.search(operators, text) # Check if operator if check_op is not None: matched_op = check_op.__getitem__(0) self.input_queue.push(self.operators[matched_op]) text = text[len(matched_op)::] continue check_func = re.search(functions, text) # Check if function if check_func is not None: matched_func = check_func.__getitem__(0) self.input_queue.push(self.functions[matched_func]) text = text[len(matched_func)::] continue return self.input_queue def calculate(self, input_str): """ Put everything together """ self.text_parser(input_str) self.convert_queue_to_rpn() return self.evaluate()
class Calculator(): def __init__(self): # Define the functions supported by linking them to Python # functions. These can be made elsewhere in the program, # or imported (e.g., from numpy) self.functions = { 'EXP': Function(numpy.exp), 'LOG': Function(numpy.log), 'SIN': Function(numpy.sin), 'COS': Function(numpy.cos), 'SQRT': Function(numpy.sqrt) } # Define the operators supported # Link them to Python functions (here: from numpy) self.operators = { 'PLUSS': Operator(numpy.add, 0), 'GANGE': Operator(numpy.multiply, 1), 'DELE': Operator(numpy.divide, 1), 'MINUS': Operator(numpy.subtract, 0) } # Define the output−queue . The parse text method fills this with RPN. # The evaluate_output_queue method evaluates it self.output_queue = Queue() self.input_queue = Queue() def evaluate_output_queue(self): if not isinstance(self.output_queue.peek(), Function) and not isinstance( self.output_queue.peek(), Operator): raise TypeError("This is not RPN") def RSAcalculation(self): sta = Stack() size = self.output_queue.size() for i in range(0, size): element = self.output_queue.pop() if isinstance(element, numbers.Number): sta.push(element) elif isinstance(element, Function): number = sta.pop() sta.push(element.execute(number)) else: #element er operator number2 = sta.pop() number1 = sta.pop() sta.push(element.execute(number1, number2)) return sta.pop() def to_RPN(self): op_stack = Stack() size_input = self.input_queue.size() for i in range(0, size_input): element = self.input_queue.peek() if isinstance(element, numbers.Number): self.output_queue.push(self.input_queue.pop()) elif isinstance(element, Function): op_stack.push(self.input_queue.pop()) elif element == "(": op_stack.push(self.input_queue.pop()) elif element == ")": el = op_stack.peek() while el != "(": self.output_queue.push(op_stack.pop()) el = op_stack.peek() op_stack.pop() self.input_queue.pop() elif isinstance(element, Operator): if not op_stack.is_empty(): el = op_stack.peek() while (isinstance(el, Operator) and el.strength >= element.strength) or isinstance( el, Function): self.output_queue.push(op_stack.pop()) if op_stack.is_empty(): break el = op_stack.peek() op_stack.push(self.input_queue.pop()) size_stack = op_stack.size() for i in range(0, size_stack): self.output_queue.push(op_stack.pop()) def textparser(self, input_txt): txt = input_txt.replace(" ", "").upper() nums = "^[-0123456789.]+" funcs = "|".join(["^" + func for func in self.functions]) ops = "|".join(["^" + op for op in self.operators]) parenths = r"^[\(\)]" while txt != "": check = re.search(nums, txt) if check is not None: txt = self.sub_string(txt, check.end) self.input_queue.push(float(check.group(0))) check = re.search(funcs, txt) if check is not None: txt = self.sub_string(txt, check.end) self.input_queue.push(self.functions[check.group(0)]) check = re.search(ops, txt) if check is not None: txt = self.sub_string(txt, check.end) self.input_queue.push(self.operators[check.group(0)]) check = re.search(parenths, txt) if check is not None: txt = self.sub_string(txt, check.end) self.input_queue.push(check.group(0)) def sub_string(self, string, end): if len(string) - 1 < end(0): return "" return string[end(0):] def calculate_expression(self, txt): self.textparser(txt) self.to_RPN() return self.RSAcalculation()