From bbe0d65b1f3630eccbdd4fc4fe9ff0f34f81505e Mon Sep 17 00:00:00 2001 From: hugogogo Date: Thu, 14 May 2026 12:31:32 +0200 Subject: [PATCH] add gcd if all int --- Makefile | 5 +-- README.md | 58 ----------------------------------- headers/computorv1.h | 23 ++++++++------ src/printer_solutions.c | 48 ++++++++++++++++++++--------- src/solver.c | 67 ++++++++++++++++++++++++++++++++++++++--- src/utils/errors.c | 10 ++++-- tester.sh | 4 +-- 7 files changed, 120 insertions(+), 95 deletions(-) diff --git a/Makefile b/Makefile index bef8498..e527b21 100644 --- a/Makefile +++ b/Makefile @@ -68,9 +68,6 @@ else RM_OBJS = rm -rf $(D_OBJS) endif -# EXECUTION FLAGS -RUN_FLAGS = -b - # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # . target: prerequisites . $@ : target # @@ -106,7 +103,7 @@ $(NAME): $(OBJS) run: $(NAME) @echo $(B_PURPLE)"\n---------------------------------------------\n1. degree 2 \n"$(RESET) - -./$(NAME) $(RUN_FLAGS) "3 * x^2 + 5 * x^1 - 2 * x^0 = 5 * x^1" + -./$(NAME) -b -d "3x² + 5x - 2 = 5x" test: $(NAME) bash tester.sh diff --git a/README.md b/README.md index 3d3050c..558ee7e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ ## todo -- create tester - if no "=" sign return error - doing gcd for int values, and not for double values - double is nearly_equal_0 @@ -20,63 +19,6 @@ this project uses submodules (maybe recursively), so either : - `git clone --recurse-submodules ` - or, after cloning : `git submodule update --init --recursive` -## steps - -1. lexer - -> tokens types : - - TOKEN_VARIABLE // x, y, etc. - - TOKEN_NUMBER_INT // int - - TOKEN_NUMBER_DOUBLE // double - - TOKEN_POWER // ^ or ** - - TOKEN_SIGN_PLUS // + - - TOKEN_SIGN_MINUS // - - - TOKEN_FACTOR_MULT // * - - TOKEN_FACTOR_DIV // / or : - - TOKEN_EQUAL // = - - END // null -2. parser - -> terms : - - POSITION // left or righ from = - - SIGN // + or - - - COEFFICIENT // double - - EXPONENT // double -3. reduce - -> polynom : - - sign - - coefficient - - exponent -4. print reduced form - -> print reduced form - -> if degree 1 : - - if c = 0 -> print "any real is a solution" - - if c != 0 -> print "no solution" - -> if degree 2 : - - print degree - -> if degree 3 : - - print degree -5. solve - -> degree 1 : - -> ax + b = 0 <=> ax = -b <=> x = -b / a - -> solution : - - a; // double - - b; // double - - solution_gcd; // gcd(b, a) - - solution_numerator; // -b / gcd - - solution_denominator; // a / gcd - - solution; // double (-b / a) - -> degree 2 : - -> discriminant : Δ = b² - 4ac - -> Δ > 0 -> 2 solutions : x = ( -b / 2a ) +- ( √|Δ| / 2a ) - -> Δ == 0 -> 1 solution : x = ( -b / 2a ) - -> Δ < 0 -> 2 solutions : x = ( -b / 2a ) +- i( √|Δ| / 2a ) - -> solution : - - delta_sign; // + or - - - delta; // Δ - - delta_absolute; // |Δ| - - delta_sqrt; // √|Δ| - - first_term; // double (-b / 2a) - - second_term; // double (√|Δ| / 2a) -6. print solution --- diff --git a/headers/computorv1.h b/headers/computorv1.h index bcb9766..1edd8bf 100644 --- a/headers/computorv1.h +++ b/headers/computorv1.h @@ -129,15 +129,20 @@ typedef struct typedef struct { - double a; // a in "ax² + bx + c" - double b; // b in "ax² + bx + c" - double c; // c in "ax² + bx + c" - e_delta_sign delta_sign; // DELTA_PLUS or DELTA_MINUS or DELTA_ZERO - double delta; // Δ == b² - 4ac - double delta_absolute; // |Δ| - double delta_sqrt; // √|Δ| - double first_term; // double (-b / 2a) - double second_term; // double (√|Δ| / 2a) + double a; // a in "ax² + bx + c" + double b; // b in "ax² + bx + c" + double c; // c in "ax² + bx + c" + e_delta_sign delta_sign; // DELTA_PLUS or DELTA_MINUS or DELTA_ZERO + double delta; // Δ == b² - 4ac + double delta_absolute; // |Δ| + double delta_sqrt; // √|Δ| + double left_term; // double (-b / 2a) + double right_term; // double (√|Δ| / 2a) + bool all_int; // false if any is double : b, a, √|Δ| + int left_term_numerator; // -b / gcd + int left_term_denominator; // 2a / gcd + int right_term_numerator; // √|Δ| / gcd + int right_term_denominator; // 2a / gcd } s_solution_degree_2; typedef struct diff --git a/src/printer_solutions.c b/src/printer_solutions.c index 6fb925a..dbdb26b 100644 --- a/src/printer_solutions.c +++ b/src/printer_solutions.c @@ -11,31 +11,49 @@ static void print_solution_degree_1(s_solution_degree_1 solution) static void print_solution_delta_zero(s_solution_degree_2 solution) { ft_printf("Discriminant is equal to zero, the solution is:\n"); - printf("%g\n", solution.first_term); + printf("%g\n", solution.left_term); } static void print_solution_delta_positiv(s_solution_degree_2 solution) { ft_printf("Discriminant is strictly positive, the two solutions are:\n"); - printf("%g\n", solution.first_term + solution.second_term); - printf("%g\n", solution.first_term - solution.second_term); + printf("%g\n", solution.left_term + solution.right_term); + printf("%g\n", solution.left_term - solution.right_term); } static void print_solution_delta_negativ(s_solution_degree_2 solution) { ft_printf("Discriminant is strictly negative, the two complex solutions are:\n"); - // solution 1 - if (solution.b) - printf("%g/%g + ", solution.b * -1, solution.a * 2); - printf("%gi/%g\n", solution.delta_sqrt, solution.a * 2); + if (solution.all_int) + { + // solution 1 + if (solution.b != 0.0) + printf("%g/%g + ", solution.b * -1, solution.a * 2); + printf("%gi/%g\n", solution.delta_sqrt, solution.a * 2); - // solution 2 - if (solution.b) - printf("%g/%g - ", solution.b * -1, solution.a * 2); + // solution 2 + if (solution.b != 0.0) + printf("%g/%g - ", solution.b * -1, solution.a * 2); + else + printf("-"); + printf("%gi/%g\n", solution.delta_sqrt, solution.a * 2); + } else - printf("-"); - printf("%gi/%g\n", solution.delta_sqrt, solution.a * 2); + { + // solution 1 + if (solution.left_term != 0.0) + printf("%g + ", solution.left_term); + if (solution.right_term != 0.0) + printf("i * %g\n", solution.right_term); + + // solution 2 + if (solution.left_term != 0.0) + printf("%g - ", solution.left_term); + else + printf("-"); + printf("i * %g\n", solution.right_term); + } } void print_solution(s_solution *solution) @@ -53,11 +71,11 @@ void print_solution(s_solution *solution) { solution_d2 = solution->solution_degree_2; delta_sign = solution_d2.delta_sign; - if (delta_sign == 0) + if (delta_sign == DELTA_ZERO) print_solution_delta_zero(solution_d2); - else if (delta_sign > 0) + else if (delta_sign == DELTA_PLUS) print_solution_delta_positiv(solution_d2); - else if (delta_sign < 0) + else if (delta_sign == DELTA_MINUS) print_solution_delta_negativ(solution_d2); else stop_errors("delta sign is wrong : '%i' , delta : '%g'", solution_d2.delta_sign, solution_d2.delta); diff --git a/src/solver.c b/src/solver.c index 91769ae..5f7c39b 100644 --- a/src/solver.c +++ b/src/solver.c @@ -32,6 +32,36 @@ static double positiv_zero(double num) return num; } +int has_decimal_part(double num) +{ + return (num != (int)num); +} + +int any_has_decimal_part(double *num, size_t len) +{ + while (len > 0) + { + if (has_decimal_part(num[len - 1])) + return 1; + len--; + } + return 0; +} + +// find GCD of two integers using euclidean algorithm +static int gcd_int(int a, int b) +{ + int tmp; + + while (b != 0) + { + tmp = b; + b = a % b; + a = tmp; + } + return abs(a); +} + static void solve_degree_1(s_solution_degree_1 *solution, double a, double b) { solution->a = a; @@ -44,6 +74,7 @@ static void solve_degree_2(s_solution_degree_2 *solution, double a, double b, do { double delta; double delta_sqrt; + int gcd; solution->a = a; solution->b = b; @@ -56,11 +87,37 @@ static void solve_degree_2(s_solution_degree_2 *solution, double a, double b, do solution->delta_sqrt = ft_sqrt(solution->delta_absolute); // √|Δ| delta_sqrt = solution->delta_sqrt; - // terms - if (b) - solution->first_term = positiv_zero(-b / (2 * a)); // -b / 2a - if (delta) - solution->second_term = positiv_zero(delta_sqrt / 2 * a); // √|Δ| / 2a + /** + * SOLVE LEFT AND RIGHT TERMS AS DOUBLES + */ + + if (b != 0.0) + solution->left_term = positiv_zero(-b / (2 * a)); // -b / 2a + if (delta != 0.0) + solution->right_term = positiv_zero(delta_sqrt / 2 * a); // √|Δ| / 2a + + /** + * COMPLEX : SOLVE TERMS AS FRACTIONS + */ + + // check + if (solution->delta_sign != DELTA_MINUS) + return; + if (any_has_decimal_part((double[]){b, a, solution->delta_sqrt}, 3)) + return; + solution->all_int = true; + + // right term + gcd = gcd_int((int)solution->delta_sqrt, (int)(a * 2)); + solution->right_term_numerator = solution->delta_sqrt / gcd; + solution->right_term_denominator = (a * 2) / gcd; + + // left term + if (b == 0.0) + return; + gcd = gcd_int((int)b, (int)(a * 2)); + solution->left_term_numerator = -b / gcd; + solution->left_term_denominator = (a * 2) / gcd; } void solve(const s_polynom *polynom, s_solution *solution) diff --git a/src/utils/errors.c b/src/utils/errors.c index ca6f88f..5251c7a 100644 --- a/src/utils/errors.c +++ b/src/utils/errors.c @@ -99,8 +99,14 @@ static void print_context_solution() dprintf(STDERR_FILENO, "delta_absolute : %15g ( |Δ| )\n", solution_d2.delta_absolute); dprintf(STDERR_FILENO, "delta_sqrt : %15g ( √|Δ| )\n", solution_d2.delta_sqrt); - dprintf(STDERR_FILENO, "first_term : %15g ( -b / 2a )\n", solution_d2.first_term); - dprintf(STDERR_FILENO, "second_term : %15g ( √|Δ| / 2a )\n", solution_d2.second_term); + dprintf(STDERR_FILENO, "left_term : %15g ( -b / 2a )\n", solution_d2.left_term); + dprintf(STDERR_FILENO, "right_term : %15g ( √|Δ| / 2a )\n", solution_d2.right_term); + + dprintf(STDERR_FILENO, "all_int : %15i ( are int : b, a, √|Δ| )\n", solution_d2.all_int); + dprintf(STDERR_FILENO, "left_term_numerator : %15i ( -b / left_gcd )\n", solution_d2.left_term_numerator); + dprintf(STDERR_FILENO, "left_term_denominator : %15i ( 2a / left_gcd )\n", solution_d2.left_term_denominator); + dprintf(STDERR_FILENO, "right_term_numerator : %15i ( √|Δ| / right_gcd )\n", solution_d2.right_term_numerator); + dprintf(STDERR_FILENO, "right_term_denominator : %15i ( 2a / right_gcd )\n", solution_d2.right_term_denominator); } ft_putchar_fd('\n', STDERR_FILENO); diff --git a/tester.sh b/tester.sh index 80f076d..8e3592f 100644 --- a/tester.sh +++ b/tester.sh @@ -99,8 +99,8 @@ run_test \ Reduced form: 2 * x^0 + 0 * x^1 + 3 * x^2 = 0 Polynomial degree: 2 Discriminant is strictly negative, the two complex solutions are: -4.89898i/6 --4.89898i/6" +-√(2/3) +√(2/3)" run_test \ "2. degree 2" \