Skip to content

Commit a537cf3

Browse files
aybarsnazlicaCascadingCascadePanquesito7
authored
feat: add bisection method (#1233)
* feat: add bisection method * fix function documentation * fix float to zero comparison * fix error definition * fix the sign function Co-authored-by: Sharon "Cass" Cassidy <[email protected]> * change float type to double type * fix sign comparison equals to zero * remove pow function * Update numerical_methods/bisection_method.c Co-authored-by: David Leal <[email protected]> * add parameter docs * update docs * Update numerical_methods/bisection_method.c Co-authored-by: David Leal <[email protected]> * Update numerical_methods/bisection_method.c Co-authored-by: David Leal <[email protected]> * update docs --------- Co-authored-by: Sharon "Cass" Cassidy <[email protected]> Co-authored-by: David Leal <[email protected]>
1 parent 2115ec8 commit a537cf3

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

numerical_methods/bisection_method.c

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/**
2+
* @file
3+
* @brief In mathematics, the [Bisection
4+
* Method](https://en.wikipedia.org/wiki/Bisection_method) is a root-finding
5+
* method that applies to any continuous function for which one knows two values
6+
* with opposite signs.
7+
* @details
8+
* The method consists of repeatedly bisecting the interval
9+
* defined by the two values and then selecting the subinterval in which the
10+
* function changes sign, and therefore must contain a root. It is a very
11+
* simple and robust method, but it is also relatively slow. Because of this,
12+
* it is often used to obtain a rough approximation to a solution which is
13+
* then used as a starting point for more rapidly converging methods.
14+
* @author [Aybars Nazlica](https://github.com/aybarsnazlica)
15+
*/
16+
17+
#include <assert.h> /// for assert
18+
#include <math.h> /// for fabs
19+
#include <stdio.h> /// for IO operations
20+
21+
#define EPSILON 0.0001 // a small positive infinitesimal quantity
22+
#define NMAX 50 // maximum number of iterations
23+
24+
/**
25+
* @brief Function to check if two input values have the same sign (the property
26+
* of being positive or negative)
27+
* @param a Input value
28+
* @param b Input value
29+
* @returns 1.0 if the input values have the same sign,
30+
* @returns -1.0 if the input values have different signs
31+
*/
32+
double sign(double a, double b)
33+
{
34+
return (a > 0 && b > 0) + (a < 0 && b < 0) - (a > 0 && b < 0) -
35+
(a < 0 && b > 0);
36+
}
37+
38+
/**
39+
* @brief Continuous function for which we want to find the root
40+
* @param x Real input variable
41+
* @returns The evaluation result of the function using the input value
42+
*/
43+
double func(double x)
44+
{
45+
return x * x * x + 2.0 * x - 10.0; // f(x) = x**3 + 2x - 10
46+
}
47+
48+
/**
49+
* @brief Root-finding method for a continuous function given two values with
50+
* opposite signs
51+
* @param x_left Lower endpoint value of the interval
52+
* @param x_right Upper endpoint value of the interval
53+
* @param tolerance Error threshold
54+
* @returns `root of the function` if bisection method succeed within the
55+
* maximum number of iterations
56+
* @returns `-1` if bisection method fails
57+
*/
58+
double bisection(double x_left, double x_right, double tolerance)
59+
{
60+
int n = 1; // step counter
61+
double middle; // midpoint
62+
63+
while (n <= NMAX)
64+
{
65+
middle = (x_left + x_right) / 2; // bisect the interval
66+
double error = middle - x_left;
67+
68+
if (fabs(func(middle)) < EPSILON || error < tolerance)
69+
{
70+
return middle;
71+
}
72+
73+
if (sign(func(middle), func(x_left)) > 0.0)
74+
{
75+
x_left = middle; // new lower endpoint
76+
}
77+
else
78+
{
79+
x_right = middle; // new upper endpoint
80+
}
81+
82+
n++; // increase step counter
83+
}
84+
return -1; // method failed (maximum number of steps exceeded)
85+
}
86+
87+
/**
88+
* @brief Self-test implementations
89+
* @returns void
90+
*/
91+
static void test()
92+
{
93+
/* Compares root value that is found by the bisection method within a given
94+
* floating point error*/
95+
assert(fabs(bisection(1.0, 2.0, 0.0001) - 1.847473) <
96+
EPSILON); // the algorithm works as expected
97+
assert(fabs(bisection(100.0, 250.0, 0.0001) - 249.999928) <
98+
EPSILON); // the algorithm works as expected
99+
100+
printf("All tests have successfully passed!\n");
101+
}
102+
103+
/**
104+
* @brief Main function
105+
* @returns 0 on exit
106+
*/
107+
int main()
108+
{
109+
test(); // run self-test implementations
110+
return 0;
111+
}

0 commit comments

Comments
 (0)