コード例 #1
0
    def _parse_expression(self):
        print("Expression before parsing : ",
              self.expression) if self._verbose is True else None

        # Removing all spaces
        self.expression = self.expression.replace(" ", "")

        print("Removing all space from the expression : ",
              self.expression) if self._verbose is True else None

        # Checking if there is any sign or operator in the expression
        ok = False
        for operator in _OPERATORS + _SIGN + "=":
            if operator in self.expression:
                ok = True
        if ok is False:
            raise NothingToDoError(
                "There is no operators or sign in the expression. Nothing to do here."
            )

        # To put before convert_signed_number because it is creating parenthesis
        self.expression = parse_sign(self.expression)
        print("Parsing signs : ",
              self.expression) if self._verbose is True else None

        self._get_vars()
        print("vars = ", self._vars_set) if self._verbose is True else None

        self.expression = convert_signed_number(expression=self.expression,
                                                accept_var=True)

        print("Convert signed numbers : ",
              self.expression) if self._verbose is True else None

        self._add_implicit_cross_operator_when_parenthesis()
        self.expression = add_implicit_cross_operator_for_vars(
            self._vars_set, self.expression)

        print("Convert implicit multiplication : ",
              self.expression) if self._verbose is True else None

        # Checking args here before converting to token
        self._check_args()

        # Transforming expression to tokens
        self.expression = convert_to_tokens(self.expression)

        print("Convert to token : ",
              self.expression) if self._verbose is True else None
        self._removing_trailing_zero_and_converting_numbers_to_float()
        print("Removing extra zero and converting numbers to float: ",
              self.expression) if self._verbose is True else None
コード例 #2
0
 def _push_right_to_left(self):
     for key, right_value in self._polynom_dict_right.items():
         try:
             left_value = self._polynom_dict_left[key]
         except:
             left_value = 0.0
         tokens = convert_to_tokens(
             convert_signed_number(
                 parse_sign(
                     add_implicit_cross_operator_for_vars(list(self.var_name), str(left_value))
                     + "-"
                     + add_implicit_cross_operator_for_vars(
                         list(self.var_name), str(right_value)
                     )
                 ),
                 accept_var=True,
             )
         )
         self._polynom_dict_left[key] = self._calculator.solve(
             tokens=tokens, verbose=self._force_calculator_verbose
         )
コード例 #3
0
 def solve(
     self,
     tokens: list,
     verbose: bool = False,
     force_calculator_verbose: bool = False,
     internal: bool = False,
 ) -> str:
     """
     Resolving str calc.
     If internal is set to true, it means that the calc is from inside the class and should check
     For vars because it should be already set.
     """
     self._tokens = tokens
     self._verbose = verbose
     print("Token inside Calculator : ", tokens) if self._verbose is True else None
     if not internal:
         self._check_vars()
     npi = self.npi_converter(self._tokens, accept_var=True if self.var_name else False)
     print("Token converted to npi system : ", npi) if self._verbose is True else None
     result = parse_sign(self.resolve_npi(npi))
     return result
コード例 #4
0
    def _reduced_form(self):
        self._reduced_form = ""
        a, b, c = "0.0", "0.0", "0.0"
        for key, value in self._polynom_dict_left.items():
            if key == "a":
                a = value
            elif key == "b":
                b = value
            else:
                c = value
        if a != "0.0":
            self._reduced_form = a
        if b != "0.0":
            self._reduced_form = self._reduced_form + "+" + b
        if c != "0.0":
            self._reduced_form = self._reduced_form + "+" + c

        if len(self._reduced_form) == 0:
            self._reduced_form = "0.0"
        self._reduced_form = parse_sign(self._reduced_form) + "=0.0"

        print("Reduced form : ", self._reduced_form)
コード例 #5
0
    def _solve_polynom_degree_two(self):
        try:
            a = get_var_multiplier(self._polynom_dict_left["a"], var_name=self.var_name)
        except:
            a = 0.0
        try:
            b = get_var_multiplier(self._polynom_dict_left["b"], var_name=self.var_name)
        except:
            b = 0.0
        try:
            c = float(self._polynom_dict_left["c"])
        except:
            c = 0.0

        print("a = ", a, " b = ", b, " c = ", c) if self._verbose is True else None

        discriminant = self._get_discriminant(a, b, c)
        if discriminant > 0:
            print("The discriminant is strictly positive.")
        elif discriminant == 0:
            print("The discriminant is exactly zero.")
        else:
            print("The discriminant is strictly negative.")
        print("discriminant = ", discriminant)
        if discriminant > 0:
            self.solution = []
            if a == 0:
                raise ValueError(
                    "The expression lead to a division by zero : ",
                    float(str((-b + my_sqrt(discriminant)))),
                    " / ",
                    a,
                )
            solution_one = str((-b + my_sqrt(discriminant)) / (2 * a))
            solution_two = str((-b - my_sqrt(discriminant)) / (2 * a))
            if solution_one == "-0.0":
                solution_one = "0.0"
            if solution_two == "-0.0":
                solution_two = "0.0"
            self.solution.append(str(my_round(float(solution_one), 6)))
            self.solution.append(str(my_round(float(solution_two), 6)))
        elif discriminant == 0:
            if a == 0:
                raise ValueError(
                    "The expression lead to a division by zero : ",
                    float(str((-b + my_sqrt(discriminant)))),
                    " / ",
                    a,
                )
            self.solution = str((-b) / (2 * a))
            if self.solution == "-0.0":
                self.solution = "0.0"
        else:
            print("There is two solutions in complex number.")
            self.solution = []
            discriminant = -discriminant
            solution_one = convert_signed_number(
                f"{-b} / (2 * {a}) + i * {my_sqrt(discriminant)} / (2 * {a})".replace(" ", "")
            )
            tokens = convert_to_tokens(
                convert_signed_number(parse_sign(solution_one), accept_var=True)
            )
            self.solution.append(
                self._calculator.solve(tokens=tokens, verbose=self._force_calculator_verbose)
            )

            solution_two = f"{-b} / (2 * {a}) - i * {my_sqrt(discriminant)} / (2 * {a})".replace(
                " ", ""
            )
            tokens = convert_to_tokens(
                convert_signed_number(parse_sign(solution_two), accept_var=True)
            )
            self.solution.append(
                self._calculator.solve(tokens=tokens, verbose=self._force_calculator_verbose)
            )
コード例 #6
0
    def resolve_npi(self, npi_list) -> str:
        stack = []
        c = 0.0
        var_is_present = True if self.var_name else False

        for elem in npi_list:
            if is_number(elem) or (var_is_present and elem in self.var_name):
                stack.append(elem)
            else:
                last_two_in_stack = stack[-2:]
                del stack[-2:]
                if len(last_two_in_stack) < 2:
                    raise IndexError(
                        "There is a problem in the npi resolver, the npi_list isn't well formated."
                    )
                # Doing var calc if there is a var
                if var_is_present and (
                    self._check_have_var(str(last_two_in_stack[0]))
                    or self._check_have_var(str(last_two_in_stack[1]))
                ):
                    # - or + operator, adding to c
                    if elem in _SIGN:
                        if not self._check_have_var(str(last_two_in_stack[0])):
                            if elem == "-":
                                c = my_round(c + float(last_two_in_stack[0]))
                                # Inverting the sign of the var because it is the second element.
                                result = self._multiply_a_var("-1", str(last_two_in_stack[1]))
                            else:
                                c = my_round(c + float(last_two_in_stack[0]))
                                result = str(last_two_in_stack[1])

                        elif not self._check_have_var(str(last_two_in_stack[1])):
                            if elem == "-":
                                c = my_round(c - float(last_two_in_stack[1]))
                            else:
                                c = my_round(c + float(last_two_in_stack[1]))
                            result = str(last_two_in_stack[0])
                        else:
                            # Adding var to var
                            result = self._add_or_substract_var_to_var(
                                operator=elem,
                                first_var=str(last_two_in_stack[0]),
                                second_var=str(last_two_in_stack[1]),
                            )
                    elif elem == "*":
                        result = self._multiply_a_var(
                            str(last_two_in_stack[0]), str(last_two_in_stack[1])
                        )
                    elif elem == "/":
                        result = self._divide_a_var(
                            str(last_two_in_stack[0]), str(last_two_in_stack[1])
                        )
                    elif elem == "^":
                        result = self._power_a_var(
                            str(last_two_in_stack[0]), str(last_two_in_stack[1])
                        )
                    else:
                        raise NotImplementedError(
                            "This type of operation with vars is not accepted for the moment."
                        )

                # Doing usual calc
                elif elem == "^":
                    result = my_round(
                        my_power(float(last_two_in_stack[0]), float(last_two_in_stack[1]))
                    )
                elif elem == "*":
                    result = my_round(float(last_two_in_stack[0]) * float(last_two_in_stack[1]))
                elif elem == "/":
                    if float(last_two_in_stack[1]) == 0.0:
                        raise ValueError(
                            "The expression lead to a division by zero : ",
                            float(last_two_in_stack[0]),
                            " / ",
                            float(last_two_in_stack[1]),
                        )
                    result = my_round(float(last_two_in_stack[0]) / float(last_two_in_stack[1]))
                elif elem == "%":
                    if float(last_two_in_stack[1]) == 0.0:
                        raise ValueError(
                            "The expression lead to a modulo zero : ",
                            float(last_two_in_stack[0]),
                            " % ",
                            float(last_two_in_stack[1]),
                        )
                    result = my_round(float(last_two_in_stack[0]) % float(last_two_in_stack[1]))
                elif elem == "+":
                    result = my_round(float(last_two_in_stack[0]) + float(last_two_in_stack[1]))
                elif elem == "-":
                    result = my_round(float(last_two_in_stack[0]) - float(last_two_in_stack[1]), 6)
                stack.append(result)

        if len(stack) > 1:
            raise Exception(
                "Unexpected error when trying to resolve npi. Maybe your input format is not accepted?"
            )

        if var_is_present:
            if c != 0.0:
                # Parse sign because could have duplicate sign with the add of the +
                return parse_sign(str(c) + "+" + str(stack[0]))
            else:
                return str(stack[0])
        else:
            return str(stack[0])
コード例 #7
0
    def _add_or_substract_var_to_var(self, operator: str, first_var: str, second_var: str):
        pattern = self.var_name
        # Checking if multiple var in first_var (ex : x + X ^ 2)
        if len(re.findall(pattern=pattern, string=first_var)) > 1:
            second_var_power = str(float(self._get_power(second_var)))
            if second_var_power != "1.0":
                # regex that match any sign or none, followed by any number or none
                # followed by the var name followed by the power of the var
                pattern = "[{sign}]*[.\d]*[\*]*{var_name}\^{second_var_power}".format(
                    var_name=self.var_name, second_var_power=second_var_power, sign=_SIGN
                )
            else:
                # Same for simple X, the var name shouln't be followed by a power operator
                pattern = "[{sign}]*[.\d]*[\*]*{var_name}(?!\^)".format(
                    var_name=self.var_name, second_var_power=second_var_power, sign=_SIGN
                )
            split = re.split(pattern=pattern, string=first_var)
            if len(split) > 1:
                search = re.search(pattern=pattern, string=first_var)
                if search is not None:
                    # Cutting respective power and convert signed numbers
                    first_var = add_implicit_cross_operator_for_vars(
                        vars_list=list(self.var_name),
                        expression=convert_signed_number(search.group(0), accept_var=True),
                    )
                    second_var = add_implicit_cross_operator_for_vars(
                        vars_list=list(self.var_name),
                        expression=convert_signed_number(second_var, accept_var=True),
                    )
                    tokens = convert_to_tokens(first_var + operator + second_var)
                    result = self.solve(tokens=tokens, internal=True)
                    if result == "0.0":
                        return parse_sign("".join(split))
                    else:
                        return parse_sign(result + "+" + "".join(split))

        first_var_power = str(self._get_power(first_var))
        second_var_power = str(self._get_power(second_var))

        # Different power
        if first_var_power != second_var_power:
            return first_var + operator + second_var

        # Cutting respective power and convert signed numbers
        first_var = add_implicit_cross_operator_for_vars(
            vars_list=list(self.var_name),
            expression=convert_signed_number(first_var.split("^")[0], accept_var=True),
        )
        second_var = add_implicit_cross_operator_for_vars(
            vars_list=list(self.var_name),
            expression=convert_signed_number(second_var.split("^")[0], accept_var=True),
        )

        removed_var1_name = first_var.replace(self.var_name, "1")
        removed_var2_name = second_var.replace(self.var_name, "1")

        tokens = convert_to_tokens(removed_var1_name + operator + removed_var2_name)
        result = self.solve(tokens, internal=True)
        if float(result) == 0:
            return "0.0"
        elif float(result) == 1:
            return self._write_power_to_var(var=self.var_name, power=first_var_power)
        else:
            return str(result) + self._write_power_to_var(var=self.var_name, power=first_var_power)