14. The Intermediate and Extreme Value Theorems

📖 Reading · 15 min
💡 Every code box below is live — edit it and hit Run.

Continuity isn't just a hygiene condition. It's a guarantee, and these two theorems are what it guarantees.

Both are existence theorems: they promise something is there without telling you where. That sounds like a weak kind of result until you notice that every root-finding algorithm ever written is built on the first one, and every optimization argument in §3 depends on the second.

The Intermediate Value Theorem

If f is continuous on [a,b] and N is any value between f(a) and f(b), then there is at least one c in (a,b) with f(c) = N.

A continuous function cannot skip values. To get from f(a) to f(b) it must pass through everything in between.

The picture is obvious and that's fine — but "obvious" is doing more work than it appears. The theorem is false over the rationals: f(x) = x^2 - 2 is continuous, f(1) = -1, f(2) = 2, and yet there is no rational c with f(c) = 0. The IVT is really a statement about \mathbb{R} having no gaps, and its proof needs the completeness axiom — §15.0.

Both hypotheses are load-bearing.

Drop continuity: f(x) = \frac1x on [-1,1] runs from -1 to 1 and never takes the value 0. (It isn't continuous at 0, and that single point ruins it.)

Drop the closed interval and you lose the endpoints you were comparing.

Using it: root-finding

The corollary you'll actually reach for:

If f is continuous on [a,b] and f(a) and f(b) have opposite signs, then f has a root in (a,b).

That's just IVT with N = 0. It's a sign change, and a sign change is something a computer can test.

Does x^3 - x - 2 = 0 have a solution? Try endpoints: f(1) = -2 and f(2) = 4. The polynomial is continuous, the signs differ, so yes — a root lies in (1,2).

Note what we did and didn't learn. We proved existence without finding it, and without factoring anything. That's the trade: existence theorems are cheap, and locations are expensive.

But you can convert one into the other by repeating: check the midpoint, keep whichever half still has a sign change, repeat. That's bisection, it halves the interval every step, and it cannot fail because the IVT re-certifies the bracket each time. Slow but bulletproof — contrast Newton's method in §3.2, which is far faster and occasionally diverges.

A less obvious use

At any moment, there are two antipodal points on the equator with exactly the same temperature.

Let T(\theta) be the temperature at angle \theta, and define

g(\theta) = T(\theta) - T(\theta + \pi)

the difference between a point and its antipode. Then

g(0) = T(0) - T(\pi), \qquad g(\pi) = T(\pi) - T(2\pi) = T(\pi) - T(0) = -g(0)

g(0) and g(\pi) are negatives of each other, so unless both are zero (in which case we're already done) they have opposite signs. By the IVT there's a \theta^* with g(\theta^*) = 0 — that is, T(\theta^*) = T(\theta^* + \pi).

Two antipodal points at the same temperature, guaranteed, with no meteorology whatsoever. This is the one-dimensional case of the Borsuk–Ulam theorem, and the technique — build an auxiliary function whose zero is what you want — is the standard move. You'll use it again for the Mean Value Theorem in §3.4.

The Extreme Value Theorem

If f is continuous on a closed, bounded interval [a,b], then f attains an absolute maximum and an absolute minimum on [a,b].

Not just boundedattained. There exist points c, d \in [a,b] with f(c) \le f(x) \le f(d) for all x.

That distinction is the entire content. "The values stay below 5" is much weaker than "some input actually produces the largest value".

Every hypothesis is necessary, and it's worth seeing each fail:

Broken hypothesis Counterexample What goes wrong
Open interval f(x) = x on (0,1) approaches 0 and 1, attains neither
Unbounded interval f(x) = x on [0,\infty) no maximum at all
Not continuous f(x) = 1/x on [0,1], with f(0)=0 unbounded above
Sneakier: open interval f(x) = \frac{1}{x(1-x)} on (0,1) has a min, no max

The EVT is why §3's optimization procedure works. To find the extremes of a continuous function on [a,b] you check the critical points and the two endpoints — a finite list — and the EVT is your assurance that the answer is somewhere on that list rather than escaping to a boundary you can't reach.

Doing it in Python

Bisection, which is the IVT run as an algorithm:

def bisect(f, a, b, steps=40):
    assert f(a) * f(b) < 0, "IVT needs a sign change to work with"
    for _ in range(steps):
        mid = (a + b) / 2
        if f(a) * f(mid) <= 0:
            b = mid          # the root is in the left half
        else:
            a = mid          # ...or the right one
    return (a + b) / 2

def f(x):
    return x**3 - x - 2

print(f"f(1) = {f(1)},  f(2) = {f(2)}  -> signs differ, so a root exists")
root = bisect(f, 1, 2)
print(f"root  = {root:.12f}")
print(f"f(root) = {f(root):.2e}")

Watch the bracket collapse — each step halves it, no exceptions:

def f(x):
    return x**3 - x - 2

a, b = 1.0, 2.0
print(f"{'step':>5} {'a':>16} {'b':>16} {'width':>12}")
for i in range(1, 13):
    mid = (a + b) / 2
    if f(a) * f(mid) <= 0:
        b = mid
    else:
        a = mid
    print(f"{i:>5} {a:>16.10f} {b:>16.10f} {b - a:>12.2e}")

print("\nwidth halves every step: 40 steps takes 1.0 down to about 1e-12")

The antipodal-temperature argument, on synthetic data:

from math import sin, cos, pi

def T(theta):
    """Some wiggly temperature profile around the equator."""
    return 15 + 10 * sin(theta) + 4 * cos(3 * theta) + 2 * sin(7 * theta + 1)

def g(theta):
    return T(theta) - T(theta + pi)

print(f"g(0)  = {g(0):+.6f}")
print(f"g(pi) = {g(pi):+.6f}   (exactly -g(0), as the algebra promised)")

a, b = 0.0, pi
for _ in range(60):
    mid = (a + b) / 2
    if g(a) * g(mid) <= 0:
        b = mid
    else:
        a = mid

theta = (a + b) / 2
print(f"\nantipodal match at theta = {theta:.8f}")
print(f"T(theta)      = {T(theta):.10f}")
print(f"T(theta + pi) = {T(theta + pi):.10f}")

And why the EVT needs its hypotheses:

print("f(x) = x on the OPEN interval (0,1), sampled ever closer to the ends:")
for k in range(1, 7):
    eps = 10.0 ** -k
    print(f"  x={eps:.0e}  f={eps:.0e}     x={1-eps:.6f}  f={1-eps:.6f}")

print("\nvalues creep toward 0 and 1 without ever reaching them.")
print("no maximum, no minimum -- and the function is perfectly continuous.")
print("closing the interval to [0,1] fixes it instantly.")

Worked example

Show that x^5 + 2x - 5 = 0 has a solution in [1,2], and locate it to within 0.01.

Existence. f(x) = x^5 + 2x - 5 is a polynomial, hence continuous everywhere, so the IVT applies on any interval.

f(1) = 1 + 2 - 5 = -2, \qquad f(2) = 32 + 4 - 5 = 31

Opposite signs, so a root exists in (1,2). ✓

Location, by bisection. Each step tests the midpoint's sign:

Interval Midpoint m f(m) Keep
[1, 2] 1.5 +5.59 [1, 1.5]
[1, 1.5] 1.25 +0.55 [1, 1.25]
[1, 1.25] 1.125 -0.94 [1.125, 1.25]
[1.125, 1.25] 1.1875 -0.26 [1.1875, 1.25]
[1.1875, 1.25] 1.21875 +0.13 [1.1875, 1.21875]

Width is now 0.03125; two more steps bring it under 0.01, giving c \approx 1.208.

How many steps do you need? The width after n steps is \frac{b-a}{2^n}, so to get below tolerance \tau:

n > \log_2\!\frac{b-a}{\tau}

For \tau = 0.01 on [1,2]: n > \log_2 100 \approx 6.64, so 7 steps. The count is known in advance and doesn't depend on the function at all — which is exactly what makes bisection so dependable and so slow. Each step buys one bit.

Your turn

1. Show \cos x = x has a solution in [0,1].

2. Does f(x) = \frac1x on [-2, 2] take the value 0? Which hypothesis fails?

3. How many bisection steps reduce [0, 1] to a bracket narrower than 10^{-6}?

Solutions

1. Rearrange into a root problem — the standard move. Let

g(x) = \cos x - x

which is continuous everywhere (difference of continuous functions).

g(0) = \cos 0 - 0 = 1 > 0, \qquad g(1) = \cos 1 - 1 \approx 0.5403 - 1 = -0.4597 < 0

Signs differ, so by the IVT there's a c \in (0,1) with g(c) = 0, i.e. \cos c = c. (The value is c \approx 0.739085, the Dottie number — the unique real fixed point of cosine, and what you get by pressing cos on a calculator repeatedly.)

2. No. f(x) = \frac1x is never zero for any x — the numerator is a constant 1.

The hypothesis that fails is continuity: f is undefined at x = 0, which lies inside [-2,2], so it is not continuous on that interval and the IVT doesn't apply.

This is exactly why the hypothesis matters. The function runs from f(-2) = -0.5 to f(2) = 0.5 and skips every value in [-0.5, 0.5] on the way — it leaps to -\infty, reappears at +\infty, and comes back down. A single point of discontinuity destroys the guarantee completely.

3. After n steps the width is 2^{-n}. Solve

2^{-n} < 10^{-6} \implies n > 6\log_2 10 \approx 19.93

so \boxed{20} steps. Note how little the tolerance buys you: each step is one bit, so 20 steps gives about 6 decimal digits, and doubling the digits means doubling the steps. Newton's method in §3.2 squares its accuracy each step instead — 6 digits in about 4 iterations from a decent start.

Check yourself in code

Implement bisection and use it on f(x) = x^3 - x - 2 over [1,2].

Print the bracket [a,b] after 1, 5, 10, and 20 steps, showing a and b to 8 decimals and the width in scientific notation with 1 decimal. Then print the root to 8 decimals.

Print exactly this:

step  1  [1.50000000, 2.00000000]  width 5.0e-01
step  5  [1.50000000, 1.53125000]  width 3.1e-02
step 10  [1.52050781, 1.52148438]  width 9.8e-04
step 20  [1.52137947, 1.52138042]  width 9.5e-07
root 1.52137995
def f(x):
    return x**3 - x - 2

a, b = 1.0, 2.0
for step in range(1, 21):
    mid = (a + b) / 2
    # keep whichever half still brackets a sign change
    if step in (1, 5, 10, 20):
        print(f"step {step:>2}  [{a:.8f}, {b:.8f}]  width {b - a:.1e}")

print(f"root {(a + b) / 2:.8f}")
def f(x):
    return x**3 - x - 2

a, b = 1.0, 2.0
for step in range(1, 21):
    mid = (a + b) / 2
    if f(a) * f(mid) <= 0:
        b = mid
    else:
        a = mid
    if step in (1, 5, 10, 20):
        print(f"step {step:>2}  [{a:.8f}, {b:.8f}]  width {b - a:.1e}")

print(f"root {(a + b) / 2:.8f}")

The IVT says a continuous function on [a,b] hits every value between f(a) and f(b), so a sign change guarantees a root — which turns into bisection, an algorithm that cannot fail and buys one bit per step. The EVT says a continuous function on a closed, bounded interval actually attains its maximum and minimum, which is what makes §3's optimization procedure finite and complete. Both are existence theorems, both need every hypothesis they state, and both are really assertions that the real line has no gaps.

Next: the \varepsilon\delta definition, actually used — proving a limit rather than describing one.