add gcd if all int
This commit is contained in:
5
Makefile
5
Makefile
@@ -68,9 +68,6 @@ else
|
|||||||
RM_OBJS = rm -rf $(D_OBJS)
|
RM_OBJS = rm -rf $(D_OBJS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# EXECUTION FLAGS
|
|
||||||
RUN_FLAGS = -b
|
|
||||||
|
|
||||||
|
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
|
||||||
# . target: prerequisites . $@ : target #
|
# . target: prerequisites . $@ : target #
|
||||||
@@ -106,7 +103,7 @@ $(NAME): $(OBJS)
|
|||||||
|
|
||||||
run: $(NAME)
|
run: $(NAME)
|
||||||
@echo $(B_PURPLE)"\n---------------------------------------------\n1. degree 2 \n"$(RESET)
|
@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)
|
test: $(NAME)
|
||||||
bash tester.sh
|
bash tester.sh
|
||||||
|
|||||||
58
README.md
58
README.md
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
## todo
|
## todo
|
||||||
|
|
||||||
- create tester
|
|
||||||
- if no "=" sign return error
|
- if no "=" sign return error
|
||||||
- doing gcd for int values, and not for double values
|
- doing gcd for int values, and not for double values
|
||||||
- double is nearly_equal_0
|
- double is nearly_equal_0
|
||||||
@@ -20,63 +19,6 @@ this project uses submodules (maybe recursively), so either :
|
|||||||
- `git clone --recurse-submodules <repo-url>`
|
- `git clone --recurse-submodules <repo-url>`
|
||||||
- or, after cloning : `git submodule update --init --recursive`
|
- 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
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -129,15 +129,20 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
double a; // a in "ax² + bx + c"
|
double a; // a in "ax² + bx + c"
|
||||||
double b; // b in "ax² + bx + c"
|
double b; // b in "ax² + bx + c"
|
||||||
double c; // c in "ax² + bx + c"
|
double c; // c in "ax² + bx + c"
|
||||||
e_delta_sign delta_sign; // DELTA_PLUS or DELTA_MINUS or DELTA_ZERO
|
e_delta_sign delta_sign; // DELTA_PLUS or DELTA_MINUS or DELTA_ZERO
|
||||||
double delta; // Δ == b² - 4ac
|
double delta; // Δ == b² - 4ac
|
||||||
double delta_absolute; // |Δ|
|
double delta_absolute; // |Δ|
|
||||||
double delta_sqrt; // √|Δ|
|
double delta_sqrt; // √|Δ|
|
||||||
double first_term; // double (-b / 2a)
|
double left_term; // double (-b / 2a)
|
||||||
double second_term; // double (√|Δ| / 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;
|
} s_solution_degree_2;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|||||||
@@ -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)
|
static void print_solution_delta_zero(s_solution_degree_2 solution)
|
||||||
{
|
{
|
||||||
ft_printf("Discriminant is equal to zero, the solution is:\n");
|
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)
|
static void print_solution_delta_positiv(s_solution_degree_2 solution)
|
||||||
{
|
{
|
||||||
ft_printf("Discriminant is strictly positive, the two solutions are:\n");
|
ft_printf("Discriminant is strictly positive, the two solutions are:\n");
|
||||||
printf("%g\n", solution.first_term + solution.second_term);
|
printf("%g\n", solution.left_term + solution.right_term);
|
||||||
printf("%g\n", solution.first_term - solution.second_term);
|
printf("%g\n", solution.left_term - solution.right_term);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_solution_delta_negativ(s_solution_degree_2 solution)
|
static void print_solution_delta_negativ(s_solution_degree_2 solution)
|
||||||
{
|
{
|
||||||
ft_printf("Discriminant is strictly negative, the two complex solutions are:\n");
|
ft_printf("Discriminant is strictly negative, the two complex solutions are:\n");
|
||||||
|
|
||||||
// solution 1
|
if (solution.all_int)
|
||||||
if (solution.b)
|
{
|
||||||
printf("%g/%g + ", solution.b * -1, solution.a * 2);
|
// solution 1
|
||||||
printf("%gi/%g\n", solution.delta_sqrt, solution.a * 2);
|
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
|
// solution 2
|
||||||
if (solution.b)
|
if (solution.b != 0.0)
|
||||||
printf("%g/%g - ", solution.b * -1, solution.a * 2);
|
printf("%g/%g - ", solution.b * -1, solution.a * 2);
|
||||||
|
else
|
||||||
|
printf("-");
|
||||||
|
printf("%gi/%g\n", solution.delta_sqrt, solution.a * 2);
|
||||||
|
}
|
||||||
else
|
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)
|
void print_solution(s_solution *solution)
|
||||||
@@ -53,11 +71,11 @@ void print_solution(s_solution *solution)
|
|||||||
{
|
{
|
||||||
solution_d2 = solution->solution_degree_2;
|
solution_d2 = solution->solution_degree_2;
|
||||||
delta_sign = solution_d2.delta_sign;
|
delta_sign = solution_d2.delta_sign;
|
||||||
if (delta_sign == 0)
|
if (delta_sign == DELTA_ZERO)
|
||||||
print_solution_delta_zero(solution_d2);
|
print_solution_delta_zero(solution_d2);
|
||||||
else if (delta_sign > 0)
|
else if (delta_sign == DELTA_PLUS)
|
||||||
print_solution_delta_positiv(solution_d2);
|
print_solution_delta_positiv(solution_d2);
|
||||||
else if (delta_sign < 0)
|
else if (delta_sign == DELTA_MINUS)
|
||||||
print_solution_delta_negativ(solution_d2);
|
print_solution_delta_negativ(solution_d2);
|
||||||
else
|
else
|
||||||
stop_errors("delta sign is wrong : '%i' , delta : '%g'", solution_d2.delta_sign, solution_d2.delta);
|
stop_errors("delta sign is wrong : '%i' , delta : '%g'", solution_d2.delta_sign, solution_d2.delta);
|
||||||
|
|||||||
67
src/solver.c
67
src/solver.c
@@ -32,6 +32,36 @@ static double positiv_zero(double num)
|
|||||||
return 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)
|
static void solve_degree_1(s_solution_degree_1 *solution, double a, double b)
|
||||||
{
|
{
|
||||||
solution->a = a;
|
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;
|
||||||
double delta_sqrt;
|
double delta_sqrt;
|
||||||
|
int gcd;
|
||||||
|
|
||||||
solution->a = a;
|
solution->a = a;
|
||||||
solution->b = b;
|
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); // √|Δ|
|
solution->delta_sqrt = ft_sqrt(solution->delta_absolute); // √|Δ|
|
||||||
delta_sqrt = solution->delta_sqrt;
|
delta_sqrt = solution->delta_sqrt;
|
||||||
|
|
||||||
// terms
|
/**
|
||||||
if (b)
|
* SOLVE LEFT AND RIGHT TERMS AS DOUBLES
|
||||||
solution->first_term = positiv_zero(-b / (2 * a)); // -b / 2a
|
*/
|
||||||
if (delta)
|
|
||||||
solution->second_term = positiv_zero(delta_sqrt / 2 * a); // √|Δ| / 2a
|
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)
|
void solve(const s_polynom *polynom, s_solution *solution)
|
||||||
|
|||||||
@@ -99,8 +99,14 @@ static void print_context_solution()
|
|||||||
dprintf(STDERR_FILENO, "delta_absolute : %15g ( |Δ| )\n", solution_d2.delta_absolute);
|
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, "delta_sqrt : %15g ( √|Δ| )\n", solution_d2.delta_sqrt);
|
||||||
|
|
||||||
dprintf(STDERR_FILENO, "first_term : %15g ( -b / 2a )\n", solution_d2.first_term);
|
dprintf(STDERR_FILENO, "left_term : %15g ( -b / 2a )\n", solution_d2.left_term);
|
||||||
dprintf(STDERR_FILENO, "second_term : %15g ( √|Δ| / 2a )\n", solution_d2.second_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);
|
ft_putchar_fd('\n', STDERR_FILENO);
|
||||||
|
|||||||
@@ -99,8 +99,8 @@ run_test \
|
|||||||
Reduced form: 2 * x^0 + 0 * x^1 + 3 * x^2 = 0
|
Reduced form: 2 * x^0 + 0 * x^1 + 3 * x^2 = 0
|
||||||
Polynomial degree: 2
|
Polynomial degree: 2
|
||||||
Discriminant is strictly negative, the two complex solutions are:
|
Discriminant is strictly negative, the two complex solutions are:
|
||||||
4.89898i/6
|
-√(2/3)
|
||||||
-4.89898i/6"
|
√(2/3)"
|
||||||
|
|
||||||
run_test \
|
run_test \
|
||||||
"2. degree 2" \
|
"2. degree 2" \
|
||||||
|
|||||||
Reference in New Issue
Block a user