15. ε–δ in practice
You've been using limits for eight lessons on intuition. This one makes the definition do work.
You will not need \varepsilon–\delta to compute a derivative or an integral — the rules handle that. You need it for three reasons: to know what the rules are claiming, to prove a limit is not something, and because every theorem in §15 is written in this language. Learning it once now is cheaper than meeting it cold later.
The definition, read as a game
\lim_{x\to a}f(x) = L means: for every \varepsilon > 0 there exists \delta > 0 such that 0 < |x - a| < \delta \implies |f(x) - L| < \varepsilon
Two players.
The challenger picks \varepsilon: "I want f(x) within 0.001 of L."
You respond with \delta: "Then keep x within \delta of a."
You win if your \delta works for every challenge. The challenger goes first, so your \delta is allowed to — and normally must — depend on \varepsilon.
The three pieces of notation:
- |f(x) - L| < \varepsilon — how close the output must be. The target.
- |x - a| < \delta — how close the input is allowed to be. Your lever.
- 0 < |x-a| — x \neq a. This is what encodes "ignore the value at the point", and it is why the definition works for \frac{f(x+h)-f(x)}{h} at h = 0.
The method
Every proof of this kind has the same two phases.
Phase 1: scratch work (backwards). Start from what you want, |f(x) - L| < \varepsilon, and manipulate until you have |x - a| < \text{something}. That something is your \delta.
Phase 2: the proof (forwards). State \delta, assume 0 < |x-a| < \delta, and derive |f(x)-L| < \varepsilon.
The scratch work is where the thinking happens; the written proof runs the reasoning in reverse. Textbooks show only phase 2, which is why these proofs look like they were pulled out of thin air.
A linear example
Prove \lim_{x\to2}(3x+1) = 7.
Scratch. We want |(3x+1) - 7| < \varepsilon. Simplify the left side:
|3x - 6| = 3|x-2|
So we want 3|x-2| < \varepsilon, i.e. |x-2| < \frac{\varepsilon}{3}. There's the \delta.
Proof. Let \varepsilon > 0 and set \delta = \frac{\varepsilon}{3}. If 0 < |x-2| < \delta then
|(3x+1)-7| = 3|x-2| < 3\delta = 3\cdot\frac{\varepsilon}{3} = \varepsilon \qquad\blacksquare
For any linear f(x) = mx+b with m \neq 0, the same computation gives \delta = \frac{\varepsilon}{|m|}: steeper functions need tighter input control, which is exactly what intuition says.
A quadratic example, where it gets interesting
Prove \lim_{x\to2}x^2 = 4.
Scratch. We want |x^2 - 4| < \varepsilon. Factor:
|x^2-4| = |x-2||x+2|
We control |x-2| directly. But |x+2| is also varying, and we can't just divide by it — \delta must be a number, not a function of x.
The fix is a two-stage trick used in essentially every nonlinear \varepsilon–\delta proof: first restrict x to a convenient neighbourhood so the nuisance factor is bounded, then handle \varepsilon.
Insist \delta \le 1. Then |x-2| < 1 means 1 < x < 3, so
|x+2| < 5
With that in hand,
|x^2-4| = |x-2||x+2| < 5|x-2|
so it's enough to have |x-2| < \frac{\varepsilon}{5}.
Proof. Let \varepsilon > 0 and set
\delta = \min\!\left(1, \frac{\varepsilon}{5}\right)
If 0 < |x-2| < \delta then \delta \le 1 gives |x+2| < 5, and \delta \le \frac\varepsilon5 gives
|x^2-4| = |x-2||x+2| < \frac{\varepsilon}{5}\cdot 5 = \varepsilon \qquad\blacksquare
The \min is the whole technique. One clause tames the nonlinearity, the other delivers the tolerance. The choice of 1 is arbitrary — any convenient bound works, and the resulting \delta differs, which is fine. \delta is never unique. Any smaller \delta also works, so you only ever have to produce some \delta, never the best one.
Proving a limit is wrong
Negate the definition and you get a tool for disproof:
\lim_{x\to a}f(x) \neq L means: there exists \varepsilon > 0 such that for every \delta > 0, some x with 0<|x-a|<\delta has |f(x)-L| \ge \varepsilon.
The quantifiers flip. Now you pick the \varepsilon that can't be met, and the opponent's \delta is the one that fails.
Show \lim_{x\to0}\frac{|x|}{x} does not exist.
Suppose the limit were some L. Take \varepsilon = 1. Whatever \delta > 0 is offered, the interval (-\delta, \delta) contains both positive and negative points, where f takes the values +1 and -1. For both to lie within 1 of L we'd need |1 - L| < 1 and |-1-L| < 1, i.e. 0 < L < 2 and -2 < L < 0 — impossible.
So no L works, and the limit does not exist. \blacksquare
The pattern: find two sequences approaching a along which f has different limits. That's the practical form of the negation, and it's how you kill \sin(1/x) too.
Doing it in Python
You can't verify "for all \varepsilon" by machine, but you can watch a proposed \delta do its job:
def f(x):
return 3 * x + 1
a, L = 2.0, 7.0
print(f"{'epsilon':>10} {'delta = eps/3':>16} {'worst |f(x)-L|':>18} {'holds':>8}")
for eps in (1.0, 0.1, 0.01, 0.001):
delta = eps / 3
worst = max(abs(f(a + s * delta * 0.999999) - L) for s in (-1, 1))
print(f"{eps:>10} {delta:>16.8f} {worst:>18.10f} {worst < eps!s:>8}")
print("\nevery challenge is met, with room to spare at the boundary")
The quadratic, where a naive \delta fails and the \min saves it:
def f(x):
return x * x
a, L = 2.0, 4.0
print("naive delta = eps (ignoring the |x+2| factor):")
for eps in (1.0, 0.5, 0.1):
delta = eps
worst = max(abs(f(a + s * delta * 0.999999) - L) for s in (-1, 1))
print(f" eps={eps:<6} delta={delta:<8} worst={worst:.6f} holds={worst < eps}")
print("\ncorrect delta = min(1, eps/5):")
for eps in (1.0, 0.5, 0.1):
delta = min(1, eps / 5)
worst = max(abs(f(a + s * delta * 0.999999) - L) for s in (-1, 1))
print(f" eps={eps:<6} delta={delta:<8} worst={worst:.6f} holds={worst < eps}")
Searching for the largest \delta that works, to see how much slack the proof leaves:
def largest_delta(f, a, L, eps, hi=2.0, steps=60):
"""Biggest d such that |f(x)-L| < eps for all 0 < |x-a| < d."""
lo = 0.0
for _ in range(steps):
mid = (lo + hi) / 2
ok = all(abs(f(a + s * mid * t) - L) < eps
for s in (-1, 1) for t in (0.25, 0.5, 0.75, 0.999999))
lo, hi = (mid, hi) if ok else (lo, mid)
return lo
print(f"{'eps':>8} {'proof delta':>14} {'largest delta':>16} {'slack':>10}")
for eps in (1.0, 0.5, 0.1, 0.01):
proof = min(1, eps / 5)
best = largest_delta(lambda x: x * x, 2.0, 4.0, eps)
print(f"{eps:>8} {proof:>14.8f} {best:>16.8f} {best/proof:>10.3f}x")
print("\nthe proof's delta is conservative, and that is fine -- it only has to work")
Disproof by two sequences:
from math import sin, pi
print("sin(1/x) along two sequences, both running to 0:")
for k in (100, 1000, 10000):
x1 = 1 / (k * pi) # sin = 0
x2 = 1 / (pi / 2 + 2 * k * pi) # sin = 1
print(f" k={k:<6} f({x1:.2e})={sin(1/x1):+.6f} f({x2:.2e})={sin(1/x2):+.6f}")
print("\nwith eps=0.4, no single L can be within 0.4 of both 0 and 1.")
print("no delta can help: both sequences enter EVERY neighbourhood of 0.")
Worked example
Prove \lim_{x\to3}(x^2 + 1) = 10.
Scratch. Target: |x^2+1-10| = |x^2-9| = |x-3||x+3| < \varepsilon.
The nuisance factor is |x+3|. Restrict with \delta \le 1: then 2 < x < 4, so 5 < x+3 < 7, giving |x+3| < 7.
Now |x-3||x+3| < 7|x-3|, so |x-3| < \frac{\varepsilon}{7} suffices.
Proof. Let \varepsilon > 0. Choose
\delta = \min\!\left(1, \frac{\varepsilon}{7}\right)
Assume 0 < |x-3| < \delta. From \delta \le 1 we get |x-3| < 1, hence |x+3| = |(x-3) + 6| \le |x-3| + 6 < 7. Therefore
|(x^2+1) - 10| = |x-3|\,|x+3| < \frac{\varepsilon}{7}\cdot7 = \varepsilon \qquad\blacksquare
Two details worth copying. The bound |x+3| \le |x-3| + 6 is the triangle inequality, and it's the standard way to bound a nuisance factor without drawing a picture. And notice the proof never needed \delta to be optimal — a conservative bound that's easy to justify beats a sharp one that's hard.
Your turn
1. Prove \lim_{x\to1}(5x-3) = 2 by finding \delta in terms of \varepsilon.
2. For \lim_{x\to3}x^2 = 9 with \varepsilon = 0.1, find a specific \delta that works.
3. Prove \lim_{x\to0}\frac{1}{x} does not exist.
Solutions
1. Scratch. |(5x-3) - 2| = |5x - 5| = 5|x-1| < \varepsilon requires |x-1| < \frac{\varepsilon}{5}.
Proof. Given \varepsilon > 0, take \delta = \frac{\varepsilon}{5}. If 0 < |x-1| < \delta then
|(5x-3)-2| = 5|x-1| < 5\cdot\frac{\varepsilon}{5} = \varepsilon \qquad\blacksquare
2. From the worked example's method with a = 3: $\delta = \min(1, \frac{\varepsilon}{7})$, so for \varepsilon = 0.1,
\delta = \min\!\left(1, \frac{0.1}{7}\right) = \frac{1}{70} \approx 0.0142857
Check the worse endpoint, x = 3 + \delta:
|(3.0142857)^2 - 9| = |9.0859 - 9| = 0.0859 < 0.1 \quad\checkmark
There's slack, as expected — the bound |x+3| < 7 was generous, since near x=3 the factor is really about 6. Using 6.1 would give a larger \delta. Both are correct proofs.
3. Suppose \lim_{x\to0}\frac1x = L for some real L. Take \varepsilon = 1.
Given any \delta > 0, pick x with $0 < x < \min\left(\delta, \frac{1}{|L|+2}\right)$. Then x is inside the \delta-neighbourhood, and
\frac1x > |L| + 2
so
\left|\frac1x - L\right| \ge \frac1x - |L| > 2 > 1 = \varepsilon
The condition fails for every \delta, so no real L can be the limit. \blacksquare
The essential point is that \frac1x is unbounded near 0, and no finite L can stay within a fixed tolerance of something unbounded. Compare the jump case \frac{|x|}{x}, where the function is bounded and the failure was disagreement rather than blow-up — two different failure modes, two different disproofs.
Check yourself in code
Verify that \delta = \varepsilon/3 certifies \lim_{x\to2}(3x+1) = 7, and that the naive \delta = \varepsilon fails for \lim_{x\to2}x^2 = 4 while \delta = \min(1, \varepsilon/5) succeeds.
For each \varepsilon \in \{1, 0.5, 0.1, 0.01\}, evaluate the worst deviation |f(x) - L| at x = a \pm 0.999999\delta and report whether it stays below \varepsilon.
Print exactly this:
linear eps=1 delta=0.333333 worst=0.999999 ok=True
linear eps=0.5 delta=0.166667 worst=0.500000 ok=True
linear eps=0.1 delta=0.033333 worst=0.100000 ok=True
linear eps=0.01 delta=0.003333 worst=0.010000 ok=True
naive eps=1 delta=1.000000 worst=4.999994 ok=False
naive eps=0.5 delta=0.500000 worst=2.249998 ok=False
naive eps=0.1 delta=0.100000 worst=0.410000 ok=False
naive eps=0.01 delta=0.010000 worst=0.040100 ok=False
min eps=1 delta=0.200000 worst=0.839999 ok=True
min eps=0.5 delta=0.100000 worst=0.410000 ok=True
min eps=0.1 delta=0.020000 worst=0.080400 ok=True
min eps=0.01 delta=0.002000 worst=0.008004 ok=True
EPS = (1, 0.5, 0.1, 0.01)
def worst(f, a, L, delta):
return max(abs(f(a + s * delta * 0.999999) - L) for s in (-1, 1))
linear = lambda x: 3 * x + 1
square = lambda x: x * x
for eps in EPS:
d = eps / 3
print(f"linear eps={eps:<6} delta={d:.6f} worst={worst(linear, 2, 7, d):.6f} "
f"ok={worst(linear, 2, 7, d) < eps}")
# now the naive delta = eps for x^2, then delta = min(1, eps/5)
EPS = (1, 0.5, 0.1, 0.01)
def worst(f, a, L, delta):
return max(abs(f(a + s * delta * 0.999999) - L) for s in (-1, 1))
linear = lambda x: 3 * x + 1
square = lambda x: x * x
for eps in EPS:
d = eps / 3
w = worst(linear, 2, 7, d)
print(f"linear eps={eps:<6} delta={d:.6f} worst={w:.6f} ok={w < eps}")
for label, rule in (("naive", lambda e: e), ("min", lambda e: min(1, e / 5))):
for eps in EPS:
d = rule(eps)
w = worst(square, 2, 4, d)
print(f"{label:<8} eps={eps:<6} delta={d:.6f} worst={w:.6f} ok={w < eps}")
The definition is a two-player game: the challenger names a tolerance \varepsilon, you produce a radius \delta, and you win by answering every challenge. Find \delta by working backwards from |f(x)-L| < \varepsilon; for nonlinear functions, use $\delta = \min(\text{something convenient}, \text{something}/\varepsilon\text{-dependent})$ so the first clause bounds the nuisance factor and the second delivers the tolerance. Negating the definition gives you disproofs, and in practice that means exhibiting two sequences with different limits.
That closes the foundations. Next module: the derivative — which is a single specific limit, taken seriously.