forked from TheAlgorithms/JavaScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
merge: Added bisection method (TheAlgorithms#827)
* feat: Added bisection method * Auto-update DIRECTORY.md Co-authored-by: ggkogkou <[email protected]> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
- Loading branch information
1 parent
f692da2
commit 2619ab6
Showing
3 changed files
with
63 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/** | ||
* | ||
* @file | ||
* @brief Find real roots of a function in a specified interval [a, b], where f(a)*f(b) < 0 | ||
* | ||
* @details Given a function f(x) and an interval [a, b], where f(a) * f(b) < 0, find an approximation of the root | ||
* by calculating the middle m = (a + b) / 2, checking f(m) * f(a) and f(m) * f(b) and then by choosing the | ||
* negative product that means Bolzano's theorem is applied,, define the new interval with these points. Repeat until | ||
* we get the precision we want [Wikipedia](https://en.wikipedia.org/wiki/Bisection_method) | ||
* | ||
* @author [ggkogkou](https://github.com/ggkogkou) | ||
* | ||
*/ | ||
|
||
const findRoot = (a, b, func, numberOfIterations) => { | ||
// Check if a given real value belongs to the function's domain | ||
const belongsToDomain = (x, f) => { | ||
const res = f(x) | ||
return !Number.isNaN(res) | ||
} | ||
if (!belongsToDomain(a, func) || !belongsToDomain(b, func)) throw Error("Given interval is not a valid subset of function's domain") | ||
|
||
// Bolzano theorem | ||
const hasRoot = (a, b, func) => { | ||
return func(a) * func(b) < 0 | ||
} | ||
if (hasRoot(a, b, func) === false) { throw Error('Product f(a)*f(b) has to be negative so that Bolzano theorem is applied') } | ||
|
||
// Declare m | ||
const m = (a + b) / 2 | ||
|
||
// Recursion terminal condition | ||
if (numberOfIterations === 0) { return m } | ||
|
||
// Find the products of f(m) and f(a), f(b) | ||
const fm = func(m) | ||
const prod1 = fm * func(a) | ||
const prod2 = fm * func(b) | ||
|
||
// Depending on the sign of the products above, decide which position will m fill (a's or b's) | ||
if (prod1 > 0 && prod2 < 0) return findRoot(m, b, func, --numberOfIterations) | ||
else if (prod1 < 0 && prod2 > 0) return findRoot(a, m, func, --numberOfIterations) | ||
else throw Error('Unexpected behavior') | ||
} | ||
|
||
export { findRoot } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { findRoot } from '../BisectionMethod' | ||
|
||
test('Equation f(x) = x^2 - 3*x + 2 = 0, has root x = 1 in [a, b] = [0, 1.5]', () => { | ||
const root = findRoot(0, 1.5, (x) => { return Math.pow(x, 2) - 3 * x + 2 }, 8) | ||
expect(root).toBe(0.9990234375) | ||
}) | ||
|
||
test('Equation f(x) = ln(x) + sqrt(x) + π*x^2 = 0, has root x = 0.36247037 in [a, b] = [0, 10]', () => { | ||
const root = findRoot(0, 10, (x) => { return Math.log(x) + Math.sqrt(x) + Math.PI * Math.pow(x, 2) }, 32) | ||
expect(Number(Number(root).toPrecision(8))).toBe(0.36247037) | ||
}) | ||
|
||
test('Equation f(x) = sqrt(x) + e^(2*x) - 8*x = 0, has root x = 0.93945851 in [a, b] = [0.5, 100]', () => { | ||
const root = findRoot(0.5, 100, (x) => { return Math.exp(2 * x) + Math.sqrt(x) - 8 * x }, 32) | ||
expect(Number(Number(root).toPrecision(8))).toBe(0.93945851) | ||
}) |