8.7 KiB
42_EXT_05_computorv1
todo
- fix error if b is 0 (b takes the value of c instead)
- doing gcd for int values, and not for double values
- double is nearly_equal_0
- if no "=" sign return error
ressources
- project intra : https://projects.intra.42.fr/projects/42cursus-computorv1
- project luke : https://github.com/LuckyLaszlo/computorv1
install
this project uses submodules (maybe recursively), so either :
git clone --recurse-submodules <repo-url>- or, after cloning :
git submodule update --init --recursive
steps
- 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
- parser
-> terms :
- POSITION // left or righ from =
- SIGN // + or -
- COEFFICIENT // double
- EXPONENT // double
- reduce
-> polynom :
- sign
- coefficient
- exponent
- 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
- 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)
- print solution
sqrt implementation
finding the square root of x
dichotomy method
the dichotomie method, or binary search, consist on dividing the range of research by 2 each time, and choosing the right one for the next iteration.
Ex :
solution
↓
|------------------------------ 1. define range bound_1 : 0
|-----------------------------| 2. define range bound_2 : x
|--------------+--------------| 3. take mid : (bound_1 + bound_2) / 2
|--------------|-------ø------| 4. choose range bound : bound_1 or bound_2
---------------|--------------- 1. range bound_1 = mid
|--------------|--------------- 2. range bound_2 = chosen previous bound
|------+-------|--------------- 3. mid
|--ø---|-------|--------------- 4. choose range
-------|----------------------- 1. range bound_1 = mid
-------|-------|--------------- 2. range bound_2 = chosen previous bound
-------|---+---|--------------- 3. mid
-------|---|-ø-|--------------- 4. choose range
-----------|------------------- 1. range bound_1 = mid
-------|---|------------------- 2. range bound_2 = chosen previous bound
-------|-+-|------------------- 3. mid
-------|-|ø|------------------- 4. choose range
---------|--------------------- 1. range bound_1 = mid
-------|-|--------------------- 2. range bound_2 = chosen previous bound
-------|+|--------------------- 3. mid
-------ø|---------------------- 4. choose range
--------|---------------------- --> solution
Newton–Raphson method
it's like a self-correcting binary search, we get rid of the step "choose range", we use the formulae x/v to find the next range, with x being the number we are trying to get the sqaure root from, and v the value found at the previous step.
Ex :
solution
↓
------------------------------| 1. define range bound_1 : v
--|---------------------------| 2. choose range bound_2 : x/v
--|-------------+-------------| 3. take mid : (v + x/v) / 2
----------------|-------------- 1. range bound_1 : v = mid
------|---------|-------------- 2. range bound_2 : x/v
------|----+----|-------------- 3. mid
-----------|------------------- 1. range bound_1 : v = mid
-|---------|------------------- 2. range bound_2 : x/v
-|----+----|------------------- 3. mid
------|------------------------ 1. range bound_1 : v = mid
------|-------|---------------- 2. range bound_2 : x/v
------|---+---|---------------- 3. mid
----------|-------------------- 1. range bound_1 : v = mid
------|---|-------------------- 2. range bound_2 : x/v
------|-+-|-------------------- 3. mid
--------|---------------------- --> solution
mathematical proof that each range is automatically in the right range :
- if the value was higher than the answer, then new value is below old value, and vice versa
- how ? :
- define
x, solutions = √x, and valuev = (old_value + x / old_value) / 2 - supposition : if
v < s, thennew_v > v, elsenew_v < v: - demonstration :
- if
v < s: v < s <=> v < √x <=> v² < x (that's actually how we know that v < s) <=> v²/v < x/v <=> v < x/v -> and is s < x/v ? : v < s <=> v < √x <=> v² < x (as previously) <=> v² < x²/x <=> v² * x < x² <=> (v * √x)² < x² <=> v * √x < x <=> v * √x < v * x/v <=> √x < x/v -> so indeed : if v < √x, then v < √x < x/v == v < s < x/v -> conclusion, the new range < v , x/v > contains the solution - the same demonstration works for
v > s
- if
- define
here is a more intuitive demonstration, with x = 20 :
- show that if
v² > x(==v > s) thenv > s > x/v, and ifv² < x(==v < s) thenv < s < x/v: 1.1. for value too highv > s: 1.1.1 whyv > x/v:- let's take initial value v = 5 :
- is 5² the solution ? 5² == 25 -> so no, 5 is not the sqrt, it's too high
v v² 0 (5) 10 15 20 25 v : |----|----|----|----|----| x/v: |---|---|---|---|---| <----- squiz it, so the previous 5 portions fit the x = 20 size 0 (4) 8 12 16 20 x/v x - the value of the new portion is 4, and we can visually see that it's lower than the previous portion 5
- so :
v > x/v1.1.2 whys > x/v: - let's take the value v = 5 :
- we already showed that it's too high, now we will see that x/v == 20/5 is too low :
v 0 (5) 10 15 20 25 v : |----|----|----|----|----| x/v: |---|---|---|---|---| <----- squizz 0 *1 *2 *3 *4 *5 -> number of portions 01234 -> portion size (x/v)²: |---|---|---|---| 0 4 8 12 16 - the portion size is smaller than the number of portions, so it's too small to be the sqrt, indeed we visually see that this portion size
x/vis a root of a smaller number :(x/v)² == 16 - so :
s > x/v1.1.3. conclusion : -
v > s - and v > x/v (<- this proof is not essential)
- and s > x/v (<- we actually only need this proof)
- so
v > s > x/v
1.2. for value too high v < s :
- this is the same demonstration but in other direction, let's just summarize it :
- let's take initial value v = 4 :
v v² 0 (4) 8 12 16 (1) v : |---|---|---|---| (2) x/v: |----|----|----|----| -----> stretch (3) 0 (5) 10 15 20 x/v x (4) 0 *1 *2 *3 *4 -> number of portions 012345 -> portion size (5) (x/v)²: |----|----|----|----|----| 0 5 10 15 20 25
- (1) : 4 is not the sqrt of x == 20, it's too smalle : (4² == 16) < 20
- (2) : stretch it, so the previous 4 portions fit the x = 20 size
- (3) : the new portion x/v == 5, is more than v == 4, so v < x/v
- (4) : portion size is bigger than number of portions, so it's too big to be the root
- (5) : indeed, we see that the portion² == (x/v)² is bigger than x, so √x < x/v == s < x/v
- so v < s < x/v