Trap the root between two points where f changes sign, then halve the interval again and again. Slow, but it never fails, and it tells you exactly how accurate it is.
A game engine throws a ball upward at 20 m/s from a 10 m roof, with air drag. When must it play the "bounce" sound?
| (s) | (m) | sign |
|---|---|---|
| 0 | 10.000 | + |
| 1 | 21.559 | + |
| 2 | 20.849 | + |
| 3 | 12.699 | + |
| 4 | 0.036 | + |
| 5 | −15.364 | − |
Conditioning and stability: accuracy needs a well-posed problem and a careful algorithm.
The first of five root-finding methods. Bisection is the safest, the slowest, and the benchmark for all the others.
| 0 | 1 | 2 | 3 | |
|---|---|---|---|---|
| −2 | −2 | +4 | +22 |
input f, a, b, tol
if f(a)·f(b) > 0: stop (no bracket)
repeat up to N times:
c ← (a + b) / 2
if f(c) = 0 or (b − a)/2 < tol:
return c
if f(a)·f(c) < 0: b ← c
else: a ← cEach pass keeps the half of the bracket where the sign changes, so the root stays trapped while the bracket halves.
| new bracket | ||||||
|---|---|---|---|---|---|---|
| 1 | 1 | 2 | 1.5 | −0.125 | [1.5, 2] | 0.5 |
| 2 | 1.5 | 2 | 1.75 | +1.609375 | [1.5, 1.75] | 0.25 |
| 3 | 1.5 | 1.75 | 1.625 | +0.666016 | [1.5, 1.625] | 0.125 |
| 4 | 1.5 | 1.625 | 1.5625 | +0.252197 | [1.5, 1.5625] | 0.0625 |
| 5 | 1.5 | 1.5625 | 1.53125 | +0.059113 | [1.5, 1.53125] | 0.03125 |
| 6 | 1.5 | 1.53125 | 1.515625 | −0.034054 | [1.515625, 1.53125] | 0.015625 |
and . Each row keeps the half where changes sign. After 6 steps: root ≈ 1.5156 with error ≤ 0.0156. True root: 1.5213797.
appears inside and outside the exponential: no algebraic rearrangement isolates it (its exact form needs the Lambert W function, not an elementary function). Bisection: s.
Good practice: validate a numerical method on a problem with a known answer before trusting it on one without.
tol, or after 100 steps as a safety net#define f(x) is the classic textbook style; a function works toof, a, b and tol, then run| 1 | 0.6 | 0.8 | 0.7 | +0.043000 | 0.1 |
| 2 | 0.6 | 0.7 | 0.65 | −0.075375 | 0.05 |
| 3 | 0.65 | 0.7 | 0.675 | −0.017453 | 0.025 |
| 4 | 0.675 | 0.7 | 0.6875 | +0.012451 | 0.0125 |
| 5 | 0.675 | 0.6875 | 0.68125 | −0.002581 | 0.00625 |
Rule of thumb: use bisection when failure is not allowed, and to get a safe starting bracket for a faster method.
| Method | Idea | Evaluations for on | Guaranteed? | Finds all roots in range? |
|---|---|---|---|---|
| Graph / guess | read the crossing off a plot | — | no; about 2 digits | yes, roughly |
| Incremental search | step from , stop at the first sign change | up to 1,000,000 | yes | yes (if is small enough) |
| Bisection | halve the bracket | 20 | yes | no: one root per bracket |
Best practice combines them: a coarse incremental search (, 10 evaluations) finds every sign change, then bisection refines each bracket in 20 more steps. Lectures 7–10 add faster refinement methods to this table.
Bisection is the benchmark: safe and predictable. Every later root-finding method keeps one of its strengths and removes one of its weaknesses.
Click a card to see the exact step where bisection runs, with a small worked example.
Where exactly: the collision step of the physics engine: find the time in the current frame at which the height function crosses zero, so the bounce happens at the right moment.
Press Run to tolerance: t = 4.002526 s (20 halvings for 10⁻⁶). Without drag it would be 4.528 s: half a second late.
Where exactly: version control. The "function" is the test result of a commit: good (old) or bad (new). The sign change is the first bad commit.
git bisect good or bad| Commits to search | Tests needed |
|---|---|
| 1,000 | 10 |
| 100,000 | 17 |
| 1,000,000 | 20 |
Same formula as today: tests needed = ⌈log₂ N⌉. Nobody tests 1,000 commits one by one.
Where exactly: the first stage of t-SNE (scikit-learn, the original implementation). For each point , find the precision so that the neighbour distribution has the chosen perplexity. Perplexity falls steadily as grows, so bisection (binary search) on always works.
| 0 | 0.5 | 1 | 2 | 5 | |
|---|---|---|---|---|---|
| Perp() | 4.000 | 2.715 | 2.046 | 1.462 | 1.041 |
Toy example: 4 neighbours at squared distances 1, 2, 4, 9 and target perplexity 2. Perp(1) > 2 > Perp(2), so the root is in [1, 2]; bisection gives β = 1.0508 (σ = 0.690). Real t-SNE repeats this for every one of thousands of points.
Where exactly: deployment of a trained classifier. The false-positive rate FPR() can only go down as the threshold goes up, so FPR() − 0.05 changes sign once.
Bisection is ideal here because FPR(t) is a step function measured on data: there is no derivative, so Newton cannot be used.
Where exactly: speech pre-processing. A 5-point moving average at 8 kHz smooths a signal; its −3 dB cut-off frequency is where the gain falls to .
Root: f ≈ 721.3 Hz. Telephone-band speech energy above this frequency is attenuated by more than half its power.
Where exactly: project appraisal: the IRR is the root of the net present value. NPV() decreases as grows, so a sign change is easy to find.
NPV(0) = 200 > 0 and NPV(0.2) = −223.4 < 0. Root r = 0.077138: the IRR is 7.71%.
The ball lands at s: bisection on , 20 halvings for (the drag-free formula would say 4.528 s).
The false position method. Replace the midpoint by the point where the chord crosses the axis: usually much faster, but with a surprising weakness.