33. Curve sketching, end to end
You now have every tool needed to describe a curve without plotting a single point. This lesson is the checklist that assembles them.
The skill isn't nostalgia for the pre-graphing-calculator era. A plotter shows you a window; the analysis tells you what's true everywhere, including where to put the window. Ask a plotting library for \frac{x^3}{x^2-1} on [-10,10] and the vertical asymptotes will render as near-vertical spikes that look like part of the curve. Only the analysis distinguishes an asymptote from a steep bit.
The checklist
- Domain. Where is f defined? (§0.2's three exclusions.)
- Intercepts. f(0) for the y-intercept; solve f(x)=0 for x-intercepts.
- Symmetry. Even (f(-x)=f(x)), odd (f(-x)=-f(x)), or periodic? Halves the work when present.
- Asymptotes. Vertical where the denominator vanishes without cancelling; horizontal or slant from \lim_{x\to\pm\infty} (§1.6).
- f': increase/decrease and critical points.
- Classify the critical points.
- f'': concavity and inflection points.
- Assemble, plotting the handful of points the analysis produced.
Steps 5–7 do the real work; 1–4 tell you where to look.
Worked example 1: a polynomial
f(x) = x^3 - 3x
Domain: all of \mathbb R.
Intercepts: f(0)=0. Solving x^3-3x = x(x^2-3) = 0 gives x = 0, \pm\sqrt3.
Symmetry: f(-x) = -x^3+3x = -f(x) — odd, so it's symmetric through the origin and analysing x\ge0 suffices.
Asymptotes: none. Polynomials have none, ever. End behaviour is dominated by x^3: down on the left, up on the right.
f': f'(x) = 3x^2-3 = 3(x-1)(x+1), zero at x=\pm1.
- x<-1: both factors negative → f'>0, increasing
- -1<x<1: signs differ → f'<0, decreasing
- x>1: f'>0, increasing
Classify: f''(x)=6x. f''(-1) = -6<0 → local max at (-1, 2). f''(1)=6>0 → local min at (1,-2).
f'': zero at x=0, negative before, positive after → inflection at (0,0). Concave down on (-\infty,0), up on (0,\infty).
The picture. Comes up from -\infty, peaks at (-1,2), descends through the origin (inflecting there), bottoms at (1,-2), then rises forever. Crosses the axis at -\sqrt3, 0, \sqrt3.
Every feature is pinned down by five numbers, and the odd symmetry means you really only had to do half of it.
Worked example 2: a rational function
f(x) = \frac{x^2}{x^2-1}
Domain: x \neq \pm1.
Intercepts: f(0) = 0, and f(x)=0 only when x=0. So the origin is the only intercept, and the curve touches the axis there rather than crossing.
Symmetry: f(-x) = \frac{x^2}{x^2-1} = f(x) — even, symmetric about the y-axis.
Asymptotes. Vertical at x=\pm1: the numerator is 1 \ne 0 there, so nothing cancels. Signs, from §1.2:
- x\to1^-: numerator \to1, denominator \to0^- → -\infty
- x\to1^+: denominator \to0^+ → +\infty
and by evenness the mirror image at x=-1.
Horizontal: degrees are equal, so the limit is the leading-coefficient ratio, y=1.
Does it cross y=1? \frac{x^2}{x^2-1}=1 gives x^2 = x^2-1, i.e. 0=-1 — never. So the curve approaches y=1 without ever reaching it.
f': by the quotient rule,
f'(x) = \frac{2x(x^2-1) - x^2(2x)}{(x^2-1)^2} = \frac{-2x}{(x^2-1)^2}
The denominator is always positive, so the sign is entirely -2x's: increasing for x<0, decreasing for x>0. One critical point, x=0.
Classify: f' goes + to - at 0, so it's a local maximum, f(0)=0.
A maximum at the origin, on a curve that runs to +\infty elsewhere — a good reminder that "local" means local. The domain is split into three intervals by the asymptotes, and each behaves independently.
f'':
f''(x) = \frac{6x^2+2}{(x^2-1)^3}
The numerator is always positive, so the sign follows (x^2-1)^3:
- |x|>1: positive → concave up
- |x|<1: negative → concave down
No inflection points — concavity changes at x=\pm1, but those aren't in the domain. A change of concavity across a vertical asymptote doesn't count.
The picture. Three separate branches, read left to right: on (-\infty,-1) it rises from y=1 toward +\infty — matching the sign analysis above, which put f' > 0 for every x<0; on (-1,1) it rises from -\infty to the origin and back down; on (1,\infty) it descends from +\infty toward y=1.
Doing it in Python
The full checklist, automated:
import sympy as sp
x = sp.Symbol('x')
def sketch(f):
print(f"f(x) = {f}")
f1, f2 = sp.diff(f, x), sp.diff(f, x, 2)
print(f" domain exclusions : {sp.solve(sp.denom(sp.together(f)), x)}")
print(f" x-intercepts : {sp.solve(f, x)}")
print(f" y-intercept : {f.subs(x, 0) if f.subs(x, 0).is_finite else 'undefined'}")
even = sp.simplify(f.subs(x, -x) - f) == 0
odd = sp.simplify(f.subs(x, -x) + f) == 0
print(f" symmetry : {'even' if even else 'odd' if odd else 'neither'}")
print(f" limit at +oo : {sp.limit(f, x, sp.oo)}")
crit = sorted([c for c in sp.solve(f1, x) if c.is_real])
print(f" f' : {sp.simplify(f1)}")
print(f" critical points : {crit}")
for c in crit:
s = f2.subs(x, c)
kind = "min" if s > 0 else "max" if s < 0 else "inconclusive"
print(f" x={c}: f={f.subs(x,c)}, f''={sp.simplify(s)} -> {kind}")
infl = sorted([c for c in sp.solve(f2, x) if c.is_real])
print(f" f'' : {sp.simplify(f2)}")
print(f" f''=0 at : {infl}")
print()
sketch(x**3 - 3*x)
sketch(x**2 / (x**2 - 1))
Why the analysis beats a plot — asymptotes are invisible to sampling:
def f(x):
return x**2 / (x**2 - 1)
print("sampling near x = 1, the way a plotter would:")
for x in (0.9, 0.99, 0.999, 1.001, 1.01, 1.1):
print(f" f({x:<6}) = {f(x):>14.4f}")
print("\na plotter joins these with line segments and draws a near-vertical")
print("stroke through the gap -- which looks exactly like part of the curve.")
print("only the algebra tells you the function is undefined at x=1.")
Confirming the curve never crosses its horizontal asymptote:
import sympy as sp
x = sp.Symbol('x')
f = x**2 / (x**2 - 1)
print(f"horizontal asymptote: y = {sp.limit(f, x, sp.oo)}")
print(f"solving f(x) = 1 : {sp.solve(sp.Eq(f, 1), x)} (no solutions)")
print("\ncompare a curve that does cross its asymptote:")
g = (2*x**2 - 3*x + 1) / (x**2 - 4)
print(f" g(x) = {g}")
print(f" asymptote y = {sp.limit(g, x, sp.oo)}")
print(f" g(x) = 2 at x = {sp.solve(sp.Eq(g, 2), x)}")
Reading concavity off a table of second derivatives:
import sympy as sp
x = sp.Symbol('x')
f = x**2 / (x**2 - 1)
f2 = sp.simplify(sp.diff(f, x, 2))
print(f"f'' = {f2}\n")
print(f"{'x':>8} {'f-double':>16} {'concavity':>14}")
for v in (-3, -2, -1.5, -0.5, 0, 0.5, 1.5, 2, 3):
val = float(f2.subs(x, v))
print(f"{v:>8} {val:>16.4f} {'up' if val > 0 else 'down':>14}")
print("\nconcavity flips at x = -1 and x = 1 -- but those are asymptotes,")
print("not points of the curve, so there are no inflection points.")
Your turn
1. Sketch f(x) = \dfrac{x}{x^2+1}: symmetry, asymptotes, extrema.
2. Sketch f(x) = xe^{-x} on [0,\infty).
3. Where does f(x)=\dfrac{x^2+1}{x} have a slant asymptote, and what is it?
Solutions
1. Symmetry: f(-x) = \frac{-x}{x^2+1} = -f(x) — odd.
Domain: all \mathbb R (x^2+1 never vanishes), so no vertical asymptotes.
Horizontal: degree 1 over degree 2, so \lim_{x\to\pm\infty} = 0. Asymptote y=0, approached from above on the right and below on the left.
f': quotient rule,
f' = \frac{(x^2+1) - x(2x)}{(x^2+1)^2} = \frac{1-x^2}{(x^2+1)^2}
Sign follows 1-x^2: negative for |x|>1, positive for |x|<1.
- Local min at x=-1, value -\frac12
- Local max at x=+1, value +\frac12
So, reading the signs left to right: the curve comes in from 0 (below), drops to the minimum -\frac12 at x=-1, rises through the origin to the maximum +\frac12 at x=1, then decays back toward 0. Range exactly \left[-\frac12,\frac12\right].
2. Intercepts: f(0)=0, and e^{-x} is never zero, so the origin is the only one.
f': product rule,
f' = e^{-x} - xe^{-x} = e^{-x}(1-x)
e^{-x}>0 always, so the sign is (1-x)'s: increasing on [0,1), decreasing on (1,\infty). Local (and global) max at x=1, value e^{-1}\approx0.368.
f'': f'' = e^{-x}(x-2), zero at x=2, changing sign there — inflection at \left(2, 2e^{-2}\right) \approx (2, 0.271).
End behaviour: \lim_{x\to\infty}xe^{-x} = 0 by the growth hierarchy (§1.6) — the exponential beats the linear factor. Horizontal asymptote y=0.
Picture: rises from the origin to a peak at (1, 0.368), then decays to zero, inflecting at x=2 on the way down. This is the shape of a gamma density, of a first-order reaction's product concentration, and of an RC circuit's current response.
3. Degree 2 over degree 1 — numerator one degree higher, so a slant asymptote exists. Divide:
\frac{x^2+1}{x} = x + \frac1x
The remainder \frac1x \to 0, so the slant asymptote is \boxed{y = x}.
There's also a vertical asymptote at x=0. And note the curve approaches y=x from above for x>0 (since \frac1x>0) and from below for x<0 — the sign of the remainder tells you which side, which the analysis gives you for free and a plot makes you squint at.
Check yourself in code
Produce a curve-sketching report for f(x) = x^3 - 3x.
Print the critical points, the solutions of f''=0, and for each critical point its value, its f'', and the classification.
Print exactly this:
critical points : [-1, 1]
inflection : [0]
x=-1 f=2 f''=-6 local maximum
x=1 f=-2 f''=6 local minimum
import sympy as sp
x = sp.Symbol('x')
f = x**3 - 3*x
f1, f2 = sp.diff(f, x), sp.diff(f, x, 2)
crit = sorted(sp.solve(f1, x))
infl = sorted(sp.solve(f2, x))
print(f"critical points : {crit}")
print(f"inflection : {infl}")
for c in crit:
# value, second derivative, and the second-derivative-test verdict
print(f"x={c} ...")
import sympy as sp
x = sp.Symbol('x')
f = x**3 - 3*x
f1, f2 = sp.diff(f, x), sp.diff(f, x, 2)
crit = sorted(sp.solve(f1, x))
infl = sorted(sp.solve(f2, x))
print(f"critical points : {crit}")
print(f"inflection : {infl}")
for c in crit:
s = f2.subs(x, c)
verdict = "local minimum" if s > 0 else "local maximum"
print(f"x={c} f={f.subs(x, c)} f''={s} {verdict}")
Domain, intercepts, symmetry, asymptotes, then f' for direction and critical points, then f'' for concavity and inflections. Symmetry halves the work when it's there; asymptotes tell you where the interesting behaviour is; and the sign analyses turn a few solved equations into a complete description. A plotter shows you one window and cheerfully draws asymptotes as if they were part of the curve — the analysis is what tells you the difference.
Next: the same machinery pointed at a question with an answer someone wants.