Skip to content

Commit 58d0853

Browse files
Added main file and test file for bisection method
1 parent 94689d8 commit 58d0853

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

search/bisection.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package search
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
// Package search provides functions for searching and root-finding algorithms.
8+
//
9+
// bisection searches for the root of the function f in the interval [a, b].
10+
// The function f must be continuous and f(a) and f(b) must have different signs.
11+
// This method uses the bisection algorithm to iteratively narrow down the interval
12+
// until the root is found within the specified tolerance or the maximum number of
13+
// iterations is reached.
14+
//
15+
// Parameters:
16+
// - f: A function that takes a float64 and returns a float64. This is the function
17+
// for which we are trying to find the root.
18+
// - a: The start of the interval.
19+
// - b: The end of the interval.
20+
// - tol: The tolerance for the root. The algorithm stops when the interval width
21+
// is less than this value.
22+
// - maxIter: The maximum number of iterations to perform.
23+
//
24+
// Returns:
25+
// - float64: The approximate root of the function.
26+
// - error: An error is returned if f(a) and f(b) do not have different signs or
27+
// if the maximum number of iterations is reached without finding the root.
28+
//
29+
// Complexity:
30+
// - Worst: O(log((b-a)/tol))
31+
// - Average: O(log((b-a)/tol))
32+
// - Best: O(1)
33+
//
34+
// Example usage:
35+
//
36+
// root, err := bisection(func(x float64) float64 { return math.Pow(x, 3) - x - 2 }, 1, 2, 1e-6, 1000)
37+
// if err != nil {
38+
// log.Fatal(err)
39+
// }
40+
// fmt.Println(root) // Output: 1.521379
41+
//
42+
// Reference:
43+
// - https://en.wikipedia.org/wiki/Bisection_method
44+
func bisection(f func(float64) float64, a, b, tol float64, maxIter int) (float64, error) {
45+
if f(a)*f(b) >= 0 {
46+
return 0, fmt.Errorf("f(a) and f(b) must have different signs")
47+
}
48+
49+
var c float64
50+
for i := 0; i < maxIter; i++ {
51+
c = (a + b) / 2
52+
if f(c) == 0 || (b-a)/2 < tol {
53+
return c, nil
54+
}
55+
if f(c)*f(a) < 0 {
56+
b = c
57+
} else {
58+
a = c
59+
}
60+
}
61+
return c, fmt.Errorf("maximum number of iterations reached")
62+
}

search/bisection_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package search
2+
3+
import (
4+
"math"
5+
"testing"
6+
)
7+
8+
func TestBisection(t *testing.T) {
9+
tests := []struct {
10+
f func(float64) float64
11+
a, b float64
12+
tol float64
13+
maxIter int
14+
want float64
15+
wantErr bool
16+
}{
17+
{
18+
f: func(x float64) float64 { return math.Pow(x, 3) - x - 2 },
19+
a: 1,
20+
b: 2,
21+
tol: 1e-6,
22+
maxIter: 1000,
23+
want: 1.521380,
24+
wantErr: false,
25+
},
26+
{
27+
f: func(x float64) float64 { return x*x - 4 },
28+
a: 0,
29+
b: 3,
30+
tol: 1e-6,
31+
maxIter: 1000,
32+
want: 2,
33+
wantErr: false,
34+
},
35+
{
36+
f: func(x float64) float64 { return x - 5 },
37+
a: 0,
38+
b: 10,
39+
tol: 1e-6,
40+
maxIter: 1000,
41+
want: 5,
42+
wantErr: false,
43+
},
44+
{
45+
f: func(x float64) float64 { return math.Sin(x) },
46+
a: 3,
47+
b: 4,
48+
tol: 1e-6,
49+
maxIter: 1000,
50+
want: math.Pi,
51+
wantErr: false,
52+
},
53+
{
54+
f: func(x float64) float64 { return x*x + 1 },
55+
a: -1,
56+
b: 1,
57+
tol: 1e-6,
58+
maxIter: 1000,
59+
want: 0,
60+
wantErr: true,
61+
},
62+
}
63+
64+
for _, tt := range tests {
65+
got, err := bisection(tt.f, tt.a, tt.b, tt.tol, tt.maxIter)
66+
if (err != nil) != tt.wantErr {
67+
t.Errorf("bisection() error = %v, wantErr %v", err, tt.wantErr)
68+
continue
69+
}
70+
if math.Abs(got-tt.want) > tt.tol {
71+
t.Errorf("bisection() = %v, want %v", got, tt.want)
72+
}
73+
}
74+
}

0 commit comments

Comments
 (0)