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)
|
||||
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
|
||||
|
||||
58
README.md
58
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 <repo-url>`
|
||||
- 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
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -136,8 +136,13 @@ typedef struct
|
||||
double delta; // Δ == b² - 4ac
|
||||
double delta_absolute; // |Δ|
|
||||
double delta_sqrt; // √|Δ|
|
||||
double first_term; // double (-b / 2a)
|
||||
double second_term; // double (√|Δ| / 2a)
|
||||
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
|
||||
|
||||
@@ -11,32 +11,50 @@ 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");
|
||||
|
||||
if (solution.all_int)
|
||||
{
|
||||
// solution 1
|
||||
if (solution.b)
|
||||
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)
|
||||
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
|
||||
{
|
||||
// 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);
|
||||
|
||||
67
src/solver.c
67
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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user