def _move_to_left(self) -> None: if not len(self._res): self.select_action(Token('0', 0)) self._moved_left = True self._possible_unary = False self.select_action(Token('-', self._position)) self.select_action(Token('(', self._position + 1))
def _second_degree(self) -> str: a = Node(Token('x', 0), 'var') a.power = 1 a.mult = 0 b = Node(Token('x', 0), 'var') b.power = 1 b.mult = 0 c = Node(Token('x', 0), 'var') c.power = 0 c.mult = 0 for val in self._terms: if val.power == 2: a = val elif val.power == 1: b = val else: c = val disc = self.discriminant(a, b, c) if disc < 0: print("Значение дискриминанта меньше 0. Действительных " "решений нет.") disc = -disc res1 = f"{-b.mult / (2 * a.mult):.2} - " \ f"{round(sqrt(disc) / (2 * a.mult), 2):.2}i" res2 = f"{-b.mult / (2 * a.mult):.2} + " \ f"{round(sqrt(disc) / (2 * a.mult), 2):.2}i" return f"Результат:\n\tX1 = {res1}, X2 = {res2}" if disc == 0: if not self._quiet: print("Дискриминант равен нулю. Доступно одно решение.") res = -b.mult / (2 * a.mult) if not round(res, 2).is_integer(): res = f"{round(res, 2):.2f}" else: res = int(res) return f"Результат:\n\tX = {res}" else: if not self._quiet: print("Дискриминант больше нуля. Доступно два решения.") res1 = (-b.mult - sqrt(disc)) / (2 * a.mult) res2 = (-b.mult + sqrt(disc)) / (2 * a.mult) if not round(res1, 2).is_integer(): res1 = f"{round(res1, 2):.2f}" else: res1 = int(res1) if not round(res2, 2).is_integer(): res2 = f"{round(res2, 2):.2f}" else: res2 = int(res2) return f"Результат:\n\tX1 = {res1}, X2 = {res2}"
def _handle_eos(self) \ -> None: if self._moved_left: self._handle_parentheses(Token(')', 0)) while not self._stack.is_empty(): val = self._stack_to_res() if val.text == '(': raise ValidateError("Brackets not balanced", val)
def _handle_operator(self, op: Token) \ -> None: if self._possible_unary and op.text in ['-', '+']: op.text = '@' if op.text == '-' else '#' while not self._stack.is_empty(): if not self._stack.check_precedence(op): break self._stack_to_res() self.__increase_stack(op) self._possible_unary = True
def _add_token(self, token: Token) -> None: if token.text in operations: token = Node(token, NODE_OP) elif token.text in unary_op: token = Node(token, NODE_UNARY) elif token.text in ['x', 'X']: token = Node(token, NODE_VAR) elif token.isdigit(): token = Node(token, NODE_NUM) else: raise ValidateError("Undefined token", token) self._stack.push(token)
def create_tokens(equation: str) -> Generator: pattern = re.compile(r"(" r"(?:[-+()])" r"|(?:[\d.]+)" r"|(?:[*/])" r"|(?:[xX])" r"|(?:\^)" r"|(?:\s+)" r"|(?:=)" r")") position: int = 0 while position < len(equation): match_obj = pattern.match(equation, position) if match_obj is None: raise ValidateError("Символ не опознан. Уравнение не валидно.", Token("", position)) text = match_obj.group(1) yield Token(text, match_obj.start(1)) position = match_obj.end()
def select_action(self, val: Token) \ -> None: if val.position >= self._position: self._position = val.position if val.text in OPS: self._handle_operator(val) elif val.text.isspace(): pass elif val.isdigit(): if self._previous_token == ')': self.select_action(Token('*', self._position)) self._res.append(val) self._possible_unary = False elif val.text in ['x', 'X']: if self.__previous_is_digit() or \ self._previous_token in ['x', 'X'] or \ self._previous_token == ')': self.select_action(Token('*', self._position)) self._res.append(val) self._possible_unary = False elif val.text == '(': self.__increase_stack(val) self._possible_unary = True elif val.text == ')': if self._previous_token in OPS: raise ValidateError( "Перед закрывающими скобками стоит " "знак операции", val) self._handle_parentheses(val) self._possible_unary = False elif val.text == '=': if self._moved_left: raise ValidateError("Not more than one quality sign allowed", val) self._handle_eos() self._move_to_left() self._possible_unary = True else: raise ValidateError(f"Unknown token '{val.text}'", val)
def test_rpn(self, tokens, res): array = (Token(val, 0) for val in tokens) res_ = rpn.ShuntingYard(array).convert() assert ' '.join([val.text for val in res_]) == res
def test_precedence(self, op, res): res_ = self.stack.check_precedence(Token(op, 0)) assert res == res_
def test_stack_push(self, op, size): self.stack.push(Token(op, 0)) assert self.stack.size == size