Monocurl Essays
Series Download

What is an integral? Adding up to get area

Distance from a changing speed, found by slicing time into pieces and adding. The definite integral is the limit of those sums, defined precisely and computed.

21 min·High school and early college·

AssumesWhat is a derivative? Speed at a single instantWhat is a limit? The epsilon-delta definition, explained

A car’s speed over ten seconds. Rectangles whose heights are the speed at the start of each slice of time add up to an estimate of the distance, and finer slices fill the region under the curve.
Monocurl source
let fh = Side(0, 10.5, 0, 22)
let Slices = |n| {
    var w = 2
    if (n > 20) {
        w = 1.2
    }
    return Boxes(fh, car, Even(0, 10, n), 0, AZURE, 0.3, w)
}
let Readout = |n| [
    center{[3.05, 0.45, 0]} Math(to_string(n), 1.15),
    center{[3.05, -0.95, 0]} Math(str_join([to_string(RSum(car, Even(0, 10, n), 0), 1), "\text{ m}"]), 1.1, AZURE)
]
mesh grid = GridLines(fh, [2, 4, 6, 8, 10], [5, 10, 15, 20])
mesh rects = Slices(5)
mesh axes = Ax(fh, [2, 4, 6, 8, 10], [5, 10, 15, 20], "t \text{ (s)}", "speed (m/s)")
mesh curve = Graph(fh, car, 0, 10, AZURE, 4.5)
mesh labels = [
    center{[3.05, 0.95, 0]} Note("slices", 0.76),
    center{[3.05, -0.4, 0]} Note("distance", 0.76)
]
mesh readout = Readout(5)

slide "refine"
    play Wait(1)
    for (n in [10, 20, 40]) {
        readout = []
        play Fade(0.25, [&readout])
        rects = Slices(n)
        readout = Readout(n)
        play Fade(0.7, [&rects, &readout])
        play Wait(0.9)
    }
    play Wait(0.8)

Uses the shared definitions for this lesson's figures.

The odometer in your car is broken, but the speedometer works. You drive for ten seconds, watching the needle wander between 8 and 20 meters per second. From the speedometer readings alone, can you work out how far you went?

If the needle had sat still, the answer would be easy: at a steady 15 m/s for 10 s you cover $15 \times 10 = 150$ meters. But the needle moved, so there is no single speed to multiply by. Use the highest reading and you overestimate; use the lowest and you underestimate. This is the mirror image of the problem in lesson 1. There we knew the distance at every moment and wanted the speed at one instant. Here we know the speed at every instant and want the distance. The answer to that question is called the integral, and like the derivative it starts as a simple idea and ends as a limit.

Distance is an area

Start with the steady case and draw it. On a graph of speed against time, a constant speed is a horizontal line, and “speed times time” is the height of that line times the width of the time interval. That product is the area of the rectangle under the line. The units agree: a height in meters per second times a width in seconds is an area in meters.

For a case where the speed changes, take the ball from lesson 1. Dropped from rest, it has fallen $s(t) = 5t^2$ meters after $t$ seconds, and we found its speed by differentiating: $v(t) = 10t$ meters per second. Forget for now that we know $s$. Given only $v(t) = 10t$, how far does the ball fall in the first 2 seconds?

Multiplying one speed by 2 seconds fails whichever speed we pick. The starting speed gives $0 \times 2 = 0$ m and the final speed gives $20 \times 2 = 40$ m. The trouble is the same as in lesson 1, where the speed changed during the interval, and so is the repair: use shorter intervals, so that the speed has less time to change. Cut the 2 seconds into four slices of half a second. Within one slice the speed changes by only 5 m/s, so pretending it is constant there is a smaller lie.

  1. A steady 15 m/s for 2 s covers 30 m. That is the area of the rectangle under the speed graph.
  2. The falling ball’s speed is 10t. It is never steady, so no single rectangle fits.
  3. Slice the time into four pieces and use the speed at the start of each: 0, 5, 10 and 15 m/s for half a second each. Total 15 m, too low.
  4. Use the speed at the end of each piece instead: 5, 10, 15 and 20 m/s. Total 25 m, too high.
Estimating how far the ball falls in 2 seconds from its speed $v(t) = 10t$. Four rectangles using the speed at the start of each half-second give 15 m, and four using the speed at the end give 25 m.
Monocurl source
let fb = Side(0, 2.2, 0, 22)
let X4 = Even(0, 2, 4)
mesh grid = GridLines(fb, [0.5, 1, 1.5, 2], [5, 10, 15, 20])
mesh up = []
mesh low = Shape([at(fb, 0, 0), at(fb, 2, 0), at(fb, 2, 15), at(fb, 0, 15)], LEAF, 0.25, 2)
mesh axes = Ax(fb, [0.5, 1, 1.5, 2], [5, 10, 15, 20], "t \text{ (s)}", "speed (m/s)", 1)
mesh line = Seg(at(fb, 0, 15), at(fb, 2, 15), AZURE, 4.5)
mesh r1 = [
    center{[3.05, 0.9, 0]} Note("steady speed", 0.74),
    center{[3.05, 0.4, 0]} Math("15 \times 2 = 30 \text{ m}", 0.85, LEAF)
]
mesh r2 = []

slide "A steady 15 m/s for 2 s covers 30 m. That is the area of the rectangle under the speed graph."
    play Fade(0.6)

slide "The falling ball's speed is 10t. It is never steady, so no single rectangle fits."
    low = []
    r1 = []
    line = Graph(fb, v, 0, 2.15, AZURE, 4.5)
    play Fade(0.7, [&low, &r1, &line])

slide "Slice the time into four pieces and use the speed at the start of each: 0, 5, 10 and 15 m/s for half a second each. Total 15 m, too low."
    low = Boxes(fb, v, X4, 0, AZURE, 0.35)
    r1 = [
        center{[3.05, 0.9, 0]} Cap("start speeds", 0.74, AZURE),
        center{[3.05, 0.4, 0]} Math(str_join([to_string(RSum(v, X4, 0), 1), "\text{ m}"]), 1.0, AZURE)
    ]
    play Fade(0.7, [&low, &r1])

slide "Use the speed at the end of each piece instead: 5, 10, 15 and 20 m/s. Total 25 m, too high."
    up = Boxes(fb, v, X4, 1, EMBER, 0.3)
    r2 = [
        center{[3.05, -0.5, 0]} Cap("end speeds", 0.74, EMBER),
        center{[3.05, -1.0, 0]} Math(str_join([to_string(RSum(v, X4, 1), 1), "\text{ m}"]), 1.0, EMBER)
    ]
    play Fade(0.7, [&up, &r2])

Uses the shared definitions for this lesson's figures.

Because the ball only ever speeds up, its speed at the start of a slice is the lowest it has during that slice, and its speed at the end is the highest. So the first sum is a guaranteed underestimate and the second a guaranteed overestimate:

$$ 0.5\,(0 + 5 + 10 + 15) = 15 \;\le\; \text{distance} \;\le\; 0.5\,(5 + 10 + 15 + 20) = 25 \text{ meters}. $$

Pause and try

Cut the 2 seconds into eight slices of a quarter second and compute both sums. How wide is the gap between them now?

Show answerHide answer

The start speeds are $0, 2.5, 5, \dots, 17.5$, which add to $70$, so the lower sum is $0.25 \times 70 = 17.5$ m. The end speeds are $2.5, 5, \dots, 20$, which add to $90$, so the upper sum is $0.25 \times 90 = 22.5$ m. The gap has gone from 10 m to 5 m. Halving the slices halved it.

Why the gap closes

The estimates are trapping the distance from both sides, and the trap is tightening. To see how fast, look at what the gap is made of. On each slice, the upper rectangle exceeds the lower one by a small rectangle sitting on top of it. Slide all of those small rectangles sideways into one column.

The gap between the upper and lower sums is the total area of the orange rectangles. Slid sideways they stack into a single column, one slice wide and 20 m/s tall, so the gap is 20 times the width of a slice.
Monocurl source
let fs = Side(0, 2.6, 0, 22)
let Slivers = |u, n| block {
    let dt = 2 / n
    for (k in range(0, n)) {
        let x0 = k * dt + u * (2.25 - k * dt)
        . Shape([at(fs, x0, v(k * dt)), at(fs, x0 + dt, v(k * dt)), at(fs, x0 + dt, v(k * dt + dt)), at(fs, x0, v(k * dt + dt))], EMBER, 0.45, 2)
    }
}
let Readout = |n| [
    center{[3.1, 0.45, 0]} Math(to_string(n), 1.15),
    center{[3.1, -0.95, 0]} Math(str_join([to_string(40 / n, 1), "\text{ m}"]), 1.1, EMBER)
]
mesh grid = GridLines(fs, [0.5, 1, 1.5, 2], [5, 10, 15, 20])
mesh low = Boxes(fs, v, Even(0, 2, 8), 0, AZURE, 0.35)
mesh gap = Slivers(u: 0, 8)
mesh axes = Ax(fs, [0.5, 1, 1.5, 2], [5, 10, 15, 20], "t \text{ (s)}", "speed (m/s)", 1)
mesh line = Graph(fs, v, 0, 2, AZURE, 4.5)
mesh labels = [
    center{[3.1, 0.95, 0]} Note("slices", 0.76),
    center{[3.1, -0.4, 0]} Cap("gap", 0.76, EMBER)
]
mesh readout = Readout(8)

slide "stack"
    play Wait(0.8)
    gap.u = 1
    play Lerp(2, [&gap])
    play Wait(1.2)
    readout = []
    play Fade(0.25, [&readout])
    low = Boxes(fs, v, Even(0, 2, 16), 0, AZURE, 0.35)
    gap = Slivers(u: 0, 16)
    readout = Readout(16)
    play Fade(0.6, [&low, &gap, &readout])
    play Wait(0.5)
    gap.u = 1
    play Lerp(2, [&gap])
    play Wait(1.5)

Uses the shared definitions for this lesson's figures.

The small rectangles have the same width, one slice, and their heights are the amounts by which the speed rises during each slice. Stacked, those rises add up to the total rise in speed from $t = 0$ to $t = 2$, which is 20 m/s, however many slices there are. With $n$ slices each of width $\frac{2}{n}$ seconds,

$$ \text{upper sum} - \text{lower sum} = 20 \cdot \frac{2}{n} = \frac{40}{n} \text{ meters}. $$

Pause and try

How many slices are needed to make the gap smaller than 10 centimeters? Smaller than a millimeter?

Show answerHide answer

We need $\frac{40}{n} < 0.1$, so $n > 400$. For a millimeter, $\frac{40}{n} < 0.001$ needs $n > 40\,000$. Any tolerance can be met by slicing finely enough, which is the pattern of a limit.

So the gap can be made smaller than any tolerance. The distance is caught between two sums that can be brought as close together as we please, and there is room for only one number between all of them.

Finding the number exactly

For the ball we can find that number, because the sums have a formula. With $n$ slices, the $k$-th slice ends at time $\frac{2k}{n}$, where the speed is $10 \cdot \frac{2k}{n}$. The upper sum is

$$ U_n = \sum_{k=1}^{n} 10 \cdot \frac{2k}{n} \cdot \frac{2}{n} = \frac{40}{n^2}\,(1 + 2 + \dots + n). $$

The sum of the first $n$ whole numbers is $\frac{n(n+1)}{2}$. (Write the sum forwards and backwards and add: each of the $n$ columns totals $n + 1$, and that counts everything twice.) Therefore

$$ U_n = \frac{40}{n^2} \cdot \frac{n(n+1)}{2} = 20 + \frac{20}{n}, \qquad L_n = U_n - \frac{40}{n} = 20 - \frac{20}{n}. $$

These agree with what we computed: $n = 4$ gives 25 and 15, and $n = 8$ gives 22.5 and 17.5. The only number that is at least $20 - \frac{20}{n}$ and at most $20 + \frac{20}{n}$ for every $n$ is 20. The ball falls 20 meters in 2 seconds, and that is $s(2) = 5 \cdot 2^2$. We have recovered the distance from the speed alone.

The picture confirms it. The region under the line $v = 10t$ from 0 to 2 is a triangle with base 2 and height 20, and its area is $\frac{1}{2} \cdot 2 \cdot 20 = 20$. The rectangles were closing in on the area under the graph.

The definition of the integral

The ball was a kind case in two ways: its speed only increased, so the start and end of each slice gave the extremes, and we cut the time into equal slices. The car’s speed rises and falls. A definition that covers it should not care where in each slice the speed is read, or whether the slices are equal. It should only require them to be short.

A general sum for the car's speed, with the ten seconds cut at 1.5, 3.5, 4.2, 7.2 and 8.5. Each rectangle's height is the speed at an arbitrary sample time inside its slice (the dots). The fourth rectangle has area f(c_4)\,\Delta x_4.
A general sum for the car’s speed, with the ten seconds cut at 1.5, 3.5, 4.2, 7.2 and 8.5. Each rectangle’s height is the speed at an arbitrary sample time inside its slice (the dots). The fourth rectangle has area $f(c_4)\,\Delta x_4$.
Monocurl source
let fc = Wide(0, 10.5, 0, 22)
let XS = [0, 1.5, 3.5, 4.2, 7.2, 8.5, 10]
let CS = [1.0, 2.2, 3.9, 6.5, 7.9, 9.6]
mesh grid = GridLines(fc, [], [5, 10, 15, 20])
mesh boxes = block {
    for (k in range(0, 6)) {
        var col = AZURE
        if (k == 3) {
            col = EMBER
        }
        let h = car(CS[k])
        . Shape([at(fc, XS[k], 0), at(fc, XS[k + 1], 0), at(fc, XS[k + 1], h), at(fc, XS[k], h)], col, 0.3, 2.5)
    }
}
mesh axes = [
    Axes(fc),
    YTicks(fc, [5, 10, 15, 20]),
    center{[fx(fc, 10.5) + 0.5, fy(fc, 0), 0]} Math("x", 0.8, SLATE),
    center{[fx(fc, 0) + 1.2, fy(fc, 22) + 0.45, 0]} Note("speed f(x) (m/s)", 0.72)
]
mesh curve = Graph(fc, car, 0, 10, AZURE, 4.5)
mesh marks = block {
    for (k in range(0, 7)) {
        . Seg([fx(fc, XS[k]), fy(fc, 0) - 0.07, 0], [fx(fc, XS[k]), fy(fc, 0) + 0.07, 0], SLATE, 2)
        . center{[fx(fc, XS[k]), fy(fc, 0) - 0.33, 0]} Math(str_join(["x_", to_string(k)]), 0.75, SLATE)
    }
    for (k in range(0, 6)) {
        . stroke{SLATE, 2} dashed{[0.08, 0.06]} Line(at(fc, CS[k], 0), at(fc, CS[k], car(CS[k])))
        . Pt(at(fc, CS[k], car(CS[k])), INK, 0.075)
    }
    . center{[fx(fc, CS[3]), fy(fc, 0) - 0.33, 0]} Math("c_4", 0.75, EMBER)
    . center{at(fc, 5.3, 4.2)} Math("f(c_4)\,\Delta x_4", 0.8, EMBER)
}

Uses the shared definitions for this lesson's figures.

This is the tolerance game of the lesson on limits, played with sums. You name a tolerance $\varepsilon$. I answer with a fineness $\delta$, and my claim is that every way of slicing more finely than $\delta$ and every way of sampling gives a sum within $\varepsilon$ of $I$. As with limits, there can be at most one such number $I$: two different candidates could not both be within half their distance of the same sum.

The notation records the construction. The sign $\int$ is a stretched letter S, for “sum”. The product $f(x)\,dx$ recalls a typical term, a height $f(c_k)$ times a small width $\Delta x_k$. The numbers $a$ and $b$ are the limits of integration. The letter $x$ is a placeholder, like the index $k$ in a sum, so $\int_a^b f(t)\,dt$ means the same thing. If $f$ is a speed in m/s and $x$ a time in s, the integral is in meters.

Is the ball’s 20 meters an integral in this demanding sense? We only checked equal slices sampled at their ends. The full statement is true, and the proof uses the function $5t^2$ in a way that is worth watching.

  1. Cut the two seconds at any times you like, here 0.5, 0.9 and 1.6, and draw the lower and upper rectangle on each slice.
  2. From 0.9 s to 1.6 s the ball truly falls 12.8 - 4.05 = 8.75 m. That is between the slice’s rectangles, 9 x 0.7 = 6.3 and 16 x 0.7 = 11.2.
  3. The same is true in every slice, and the true distances stack up to exactly 20 m. So 20 lies between the lower and upper sums, wherever the cuts are.
The speed $10t$ (left) and the distance $5t^2$ (right), with the two seconds cut at arbitrary times 0.5, 0.9 and 1.6. In each slice the true distance fallen lies between the slice’s lower and upper rectangles, and the true distances stack to 20 m.
Monocurl source
let fl = Frame(0, 2.2, 0, 22, [-1.75, -0.2, 0], 2.9, 2.9)
let fd = Frame(0, 2.2, 0, 22, [2.05, -0.2, 0], 2.9, 2.9)
let P = [0, 0.5, 0.9, 1.6, 2]
let s = |t| 5 * t * t
let Panel = |f, name, col| [
    Axes(f),
    XTicks(f, [1, 2]),
    YTicks(f, [10, 20]),
    center{[fx(f, 1.1), fy(f, 22) + 0.55, 0]} Cap(name, 0.76, col)
]
let Rise = |k, col, w| [
    Seg(at(fd, P[k], s(P[k])), at(fd, P[k + 1], s(P[k])), SLATE, 2),
    Seg(at(fd, P[k + 1], s(P[k])), at(fd, P[k + 1], s(P[k + 1])), col, w)
]
mesh grids = [GridLines(fl, [0.5, 1, 1.5, 2], [5, 10, 15, 20]), GridLines(fd, [0.5, 1, 1.5, 2], [5, 10, 15, 20])]
mesh up = []
mesh low = []
mesh panels = [Panel(fl, "speed (m/s)", AZURE), Panel(fd, "distance (m)", LEAF)]
mesh lines = [Graph(fl, v, 0, 2.15, AZURE, 4), Graph(fd, s, 0, 2.05, LEAF, 4)]
mesh pick = []
mesh rises = []
mesh dots = []

slide "Cut the two seconds at any times you like, here 0.5, 0.9 and 1.6, and draw the lower and upper rectangle on each slice."
    up = Boxes(fl, v, P, 1, EMBER, 0.3)
    low = Boxes(fl, v, P, 0, AZURE, 0.35)
    play Fade(0.7)

slide "From 0.9 s to 1.6 s the ball truly falls 12.8 - 4.05 = 8.75 m. That is between the slice's rectangles, 9 x 0.7 = 6.3 and 16 x 0.7 = 11.2."
    pick = Outline([at(fl, 0.9, 0), at(fl, 1.6, 0), at(fl, 1.6, 16), at(fl, 0.9, 16)], INK, 3.5)
    rises = Rise(2, INK, 5)
    dots = [Pt(at(fd, 0.9, s(0.9)), INK, 0.075), Pt(at(fd, 1.6, s(1.6)), INK, 0.075)]
    play Fade(0.7, [&pick, &rises, &dots])

slide "The same is true in every slice, and the true distances stack up to exactly 20 m. So 20 lies between the lower and upper sums, wherever the cuts are."
    pick = []
    rises = map(range(0, 4), |k| Rise(k, [EMBER, PLUM, INK, GOLD][k], 5))
    dots = map(P, |t| Pt(at(fd, t, s(t)), INK, 0.075))
    play Fade(0.7, [&pick, &rises, &dots])

Uses the shared definitions for this lesson's figures.

Step 2 is where the answer came from. The true distance fallen during a slice, $5x_k^2 - 5x_{k-1}^2$, sat between that slice’s rectangles, and adding the true distances gave the total with no error. We could do this because we already knew a function, $5t^2$, whose rate of change is $10t$. Whether that can always be arranged is the subject of the next lesson.

Without such a function in hand, how do we know an integral exists at all? For the functions calculus mostly deals with, a theorem settles it.

We will use this theorem without proving it. The proof belongs to a course in real analysis, where it rests on the fact that a continuous function on a closed interval is uniformly continuous (the Heine–Cantor theorem): one $\delta$ controls the variation of $f$ across every slice at once. It is believable from what we saw. For the ball, the gap between upper and lower sums was a stack of small rises times a slice width. For a continuous function, the rise and fall within each slice can be made small everywhere by slicing finely, and the same squeeze results.

The theorem makes computation practical. Once we know the integral exists, every sequence of Riemann sums whose mesh shrinks to 0 must approach it, so we may pick the most convenient one: equal slices, sampled at the right end.

  1. Four slices, sampled at their right ends: the sum is 0.4688.
  2. Sixteen slices: 0.3652.
  3. Sixty-four slices, drawn as one staircase: 0.3412. The formula says the sums approach one third.
Right-end rectangles under $y = x^2$ on $[0, 1]$ with 4, 16 and 64 slices. Their total area decreases toward $\frac{1}{3}$.
Monocurl source
let fp = Side(0, 1.1, 0, 1.1)
let sq = |x| x * x
# the same rectangles drawn as one staircase, for when their sides would crowd into hatching
let Stair = |n| {
    var pts = []
    for (k in range(0, n)) {
        let h = sq((k + 1) / n)
        pts .= at(fp, k / n, h)
        pts .= at(fp, (k + 1) / n, h)
    }
    pts .= at(fp, 1, 0)
    return Shape(pts, EMBER, 0.3, 1.5)
}
let Readout = |n| [
    center{[3.05, 1.0, 0]} Math(to_string(n), 1.15),
    center{[3.05, -0.05, 0]} Math(to_string(RSum(sq, Even(0, 1, n), 1), 4), 1.1, EMBER)
]
mesh grid = GridLines(fp, [0.25, 0.5, 0.75, 1], [0.25, 0.5, 0.75, 1])
mesh rects = Boxes(fp, sq, Even(0, 1, 4), 1, EMBER, 0.3)
mesh axes = [
    Axes(fp),
    XTicks(fp, [0.5, 1], SLATE, 1),
    YTicks(fp, [0.5, 1], SLATE, 1),
    center{[fx(fp, 1.1) + 0.5, fy(fp, 0), 0]} Math("x", 0.8, SLATE),
    center{[fx(fp, 0) + 0.5, fy(fp, 1.1) + 0.45, 0]} Math("y = x^2", 0.8, AZURE)
]
mesh curve = Graph(fp, sq, 0, 1.04, AZURE, 4.5)
mesh labels = [
    center{[3.05, 1.5, 0]} Note("slices", 0.76),
    center{[3.05, 0.45, 0]} Cap("sum", 0.76, EMBER)
]
mesh readout = Readout(4)
mesh answer = []

slide "Four slices, sampled at their right ends: the sum is 0.4688."
    play Fade(0.6)

slide "Sixteen slices: 0.3652."
    readout = []
    play Fade(0.25, [&readout])
    rects = Boxes(fp, sq, Even(0, 1, 16), 1, EMBER, 0.3)
    readout = Readout(16)
    play Fade(0.7, [&rects, &readout])

slide "Sixty-four slices, drawn as one staircase: 0.3412. The formula says the sums approach one third."
    readout = []
    play Fade(0.25, [&readout])
    rects = Stair(64)
    readout = Readout(64)
    answer = [
        center{[3.05, -0.6, 0]} Cap("limit", 0.76, LEAF),
        center{[3.05, -1.1, 0]} Math("0.3333\ldots", 1.1, LEAF)
    ]
    play Fade(0.7, [&rects, &readout, &answer])

Uses the shared definitions for this lesson's figures.

When the function goes negative

Nothing in the definition asks $f$ to be positive. Where $f(c_k) < 0$, the term $f(c_k)\,\Delta x_k$ is negative, and the sum counts that rectangle against the total.

Pause and try

A ball is thrown straight up at 10 m/s, so its upward velocity is $v(t) = 10 - 10t$ m/s. Compute the Riemann sums for $v$ on $[0, 2]$ with four equal slices, sampling first at the left ends and then at the right ends. What do you expect $\int_0^2 v(t)\,dt$ to be, and what would that mean?

Show answerHide answer

The slices have width $0.5$. Left ends: $v = 10, 5, 0, -5$, giving $0.5 \times 10 = 5$. Right ends: $v = 5, 0, -5, -10$, giving $0.5 \times (-10) = -5$. The integral is trapped between and by symmetry should be 0. It means that after 2 seconds the ball is back at the height it was thrown from.

The upward velocity v(t) = 10 - 10t of a ball thrown upward. The region above the axis counts as +5 m and the region below as -5 m, so the integral from 0 to 2 is 0.
The upward velocity $v(t) = 10 - 10t$ of a ball thrown upward. The region above the axis counts as $+5$ m and the region below as $-5$ m, so the integral from 0 to 2 is 0.
Monocurl source
let fn = Frame(0, 2.2, -12, 12, [0.05, -0.05, 0], 6.2, 3.3)
let up_v = |t| 10 - 10 * t
mesh grid = GridLines(fn, [0.5, 1, 1.5, 2], [-10, -5, 5, 10])
mesh regions = [
    Region([at(fn, 0, 0), at(fn, 1, 0), at(fn, 0, 10)], tint(AZURE, 0.3)),
    Region([at(fn, 1, 0), at(fn, 2, 0), at(fn, 2, -10)], tint(ROSE, 0.3))
]
mesh axes = [
    Axes(fn),
    XTicks(fn, [0.5, 1.5, 2], SLATE, 1),
    YTicks(fn, [-10, -5, 5, 10]),
    center{[fx(fn, 2.2) + 0.6, fy(fn, 0), 0]} Math("t \text{ (s)}", 0.8, SLATE),
    center{[fx(fn, 0) + 1.35, fy(fn, 12) + 0.3, 0]} Note("upward velocity (m/s)", 0.72)
]
mesh line = Graph(fn, up_v, 0, 2.15, AZURE, 4.5)
mesh labels = [
    center{at(fn, 0.3, 3.4)} Math("+5 \text{ m}", 0.95, AZURE),
    center{at(fn, 1.72, -4.2)} Math("-5 \text{ m}", 0.95, ROSE),
    center{at(fn, 1.45, 6.5)} Cap("rising: 5 m up", 0.74, AZURE),
    center{at(fn, 0.62, -6.5)} Cap("falling: 5 m back down", 0.74, ROSE)
]

Uses the shared definitions for this lesson's figures.

So the integral is a signed area: area above the axis minus area below it. For a velocity this is the right bookkeeping, because the integral of velocity is the net change in position, with motion backwards undoing motion forwards. The ball travels 10 meters in total and ends where it began. If you want the total distance, integrate the speed $|v(t)|$ instead.

Three properties we will need

The integral inherits its rules from sums. These three are used constantly, and the next lesson depends on the second and third.

Property 2 is the picture of a region caught between a short rectangle of height $m$ and a tall one of height $M$. Two conventions extend the notation: $\int_a^a f(x)\,dx = 0$, and $\int_b^a f(x)\,dx = -\int_a^b f(x)\,dx$ when the limits are written backwards. With them, additivity holds for $a$, $b$, $c$ in any order.

Functions with no integral

The hypothesis of continuity can be weakened but not dropped. Let $D(x) = 1$ when $x$ is rational and $D(x) = 0$ when $x$ is irrational. Every slice of every partition of $[0, 1]$ contains both kinds of number (a fact about the real numbers that we quote). Sampling at rational points gives a Riemann sum of $\sum 1 \cdot \Delta x_k = 1$, and sampling at irrational points gives 0, however fine the mesh. No number $I$ is within $\frac{1}{2}$ of both, so $D$ is not integrable. The definition also fails for unbounded functions such as $\frac{1}{x}$ on $[0, 1]$ (with any value assigned at 0): the sample point in the first slice can be chosen to make the sum as large as you like.

Check yourself

Using two equal slices sampled at their right ends, what is the Riemann sum for $\int_0^2 x^2\,dx$?

What was hard

The idea of slicing and adding is ancient; Archimedes found areas this way. The hard part was saying what the sums approach without appealing to “infinitely thin” rectangles, and Riemann’s definition of 1854 does it with the same tolerance game as the limit. Notice also how much work one integral took. We needed a formula for $1^2 + 2^2 + \dots + n^2$ just to integrate $x^2$. The proof for the ball avoided all summation by knowing a function whose derivative was the integrand, and the next lesson shows that this shortcut is a theorem.

Problems

The first two repeat the lesson’s moves, the next four combine them, and the last two extend them.

Problem 1

An object moves with speed $v(t) = 3t$ m/s. Using four equal slices of $[0, 4]$, compute the lower and upper sums for the distance covered. Then find the exact distance from the area of a triangle.

Show solutionHide solution

The slices have width 1. The speed increases, so the lower sum samples at left ends: $3(0 + 1 + 2 + 3) \cdot 1 = 18$ m. The upper sum samples at right ends: $3(1 + 2 + 3 + 4) \cdot 1 = 30$ m. The region under $v = 3t$ from 0 to 4 is a triangle with base 4 and height 12, of area $\frac{1}{2} \cdot 4 \cdot 12 = 24$ m, which lies between the two sums (here exactly halfway).

Problem 2

A cart’s velocity along a track is $v(t) = 6 - 2t$ m/s. Using areas of triangles, find $\int_0^3 v(t)\,dt$ and $\int_0^5 v(t)\,dt$. How far has the cart travelled in total during the first 5 seconds?

Show solutionHide solution

The velocity is positive until $t = 3$ and negative after. From 0 to 3 the region is a triangle above the axis with base 3 and height 6: $\int_0^3 v\,dt = 9$ m. From 3 to 5 it is a triangle below the axis with base 2 and height $|v(5)| = 4$, of area 4, counted negatively. By additivity $\int_0^5 v\,dt = 9 - 4 = 5$ m: the cart ends 5 m ahead of where it started. The total distance travelled is $9 + 4 = 13$ m.

Problem 3

Compute $\displaystyle\int_0^b x\,dx$ for $b > 0$ from the definition, using equal slices sampled at their right ends.

Show solutionHide solution

The function is continuous, so the integral exists and right-end sums approach it. With slices of width $\frac{b}{n}$ and right ends $\frac{kb}{n}$,

$$ R_n = \sum_{k=1}^{n} \frac{kb}{n} \cdot \frac{b}{n} = \frac{b^2}{n^2} \cdot \frac{n(n+1)}{2} = \frac{b^2}{2}\left(1 + \frac{1}{n}\right). $$

As $n$ grows this approaches $\frac{b^2}{2}$, so $\int_0^b x\,dx = \frac{b^2}{2}$. Check: the region is a triangle with base $b$ and height $b$.

Problem 4

Compute $\displaystyle\int_0^2 x^2\,dx$ from right-end sums with equal slices. How many slices are needed before the right-end sum is within $0.01$ of the integral?

Show solutionHide solution

With width $\frac{2}{n}$ and right ends $\frac{2k}{n}$,

$$ R_n = \sum_{k=1}^{n} \frac{4k^2}{n^2} \cdot \frac{2}{n} = \frac{8}{n^3} \cdot \frac{n(n+1)(2n+1)}{6} = \frac{4}{3}\left(1 + \frac{1}{n}\right)\left(2 + \frac{1}{n}\right). $$

This approaches $\frac{4}{3} \cdot 2 = \frac{8}{3}$, so $\int_0^2 x^2\,dx = \frac{8}{3}$. Expanding, $R_n = \frac{8}{3} + \frac{4}{n} + \frac{4}{3n^2}$, so the error is $\frac{4}{n} + \frac{4}{3n^2}$. At $n = 400$ this is slightly more than $0.01$; at $n = 401$ it is $0.009975 + 0.000008 < 0.01$. So 401 slices are needed.

Problem 5

Let $f$ be increasing and continuous on $[a, b]$, and cut $[a, b]$ into $n$ equal slices. Show that the upper sum minus the lower sum equals $\bigl(f(b) - f(a)\bigr)\frac{b - a}{n}$. Use this to say how many slices guarantee an estimate of $\int_0^2 x^3\,dx$ that is within $0.001$ of the true value.

Show solutionHide solution

Because $f$ is increasing, its smallest value on a slice is at the left end and its largest at the right end. So $U - L = \sum \bigl(f(x_k) - f(x_{k-1})\bigr)\frac{b-a}{n}$. The sum of the differences telescopes to $f(x_n) - f(x_0) = f(b) - f(a)$. This is the stacked column from the lesson. For $x^3$ on $[0, 2]$ the gap is $(8 - 0) \cdot \frac{2}{n} = \frac{16}{n}$. The integral lies between $L$ and $U$ (apply the bounds property on each slice and add, using additivity), and so does every Riemann sum on that partition, so any of them is within $\frac{16}{n}$ of the integral. That is below $0.001$ once $n > 16\,000$.

Problem 6

Without computing the integral, show that $2 \le \displaystyle\int_0^2 \sqrt{1 + x^3}\,dx \le 6$.

Show solutionHide solution

On $[0, 2]$ the quantity $1 + x^3$ increases from 1 to 9, so $1 \le \sqrt{1 + x^3} \le 3$. The function is continuous, so the bounds property applies with $m = 1$, $M = 3$ and $b - a = 2$: the integral lies between $1 \cdot 2 = 2$ and $3 \cdot 2 = 6$.

Problem 7

Derive the formula $1^2 + 2^2 + \dots + n^2 = \dfrac{n(n+1)(2n+1)}{6}$ by adding the identity $(k+1)^3 - k^3 = 3k^2 + 3k + 1$ over $k = 1, \dots, n$.

Show solutionHide solution

The left sides telescope to $(n+1)^3 - 1$. Writing $Q$ for the sum of squares, the right sides add to $3Q + 3 \cdot \frac{n(n+1)}{2} + n$. So

$$ 3Q = (n+1)^3 - 1 - n - \frac{3n(n+1)}{2} = (n+1)\left[(n+1)^2 - 1 - \frac{3n}{2}\right] = (n+1)\left(n^2 + \frac{n}{2}\right) = \frac{n(n+1)(2n+1)}{2}, $$

where the second equality uses $-1 - n = -(n+1)$. Dividing by 3 gives the formula. Check at $n = 3$: $1 + 4 + 9 = 14$ and $\frac{3 \cdot 4 \cdot 7}{6} = 14$.

Problem 8

Imitate the proof for $10t$ to prove from the definition that $\displaystyle\int_0^b 3t^2\,dt = b^3$ for $b > 0$. (Use $x_k^3 - x_{k-1}^3 = (x_k^2 + x_kx_{k-1} + x_{k-1}^2)\,\Delta x_k$.)

Show solutionHide solution

Take any partition of $[0, b]$ with mesh $\mu$ and any sample points, with Riemann sum $S$. Let $L = \sum 3x_{k-1}^2\,\Delta x_k$ and $U = \sum 3x_k^2\,\Delta x_k$. Since $3t^2$ is increasing for $t \ge 0$, $L \le S \le U$. Since $0 \le x_{k-1} < x_k$, each of the three terms in $x_k^2 + x_kx_{k-1} + x_{k-1}^2$ is at least $x_{k-1}^2$ and at most $x_k^2$, so

$$ 3x_{k-1}^2\,\Delta x_k \le x_k^3 - x_{k-1}^3 \le 3x_k^2\,\Delta x_k. $$

Adding over $k$, the middle telescopes to $b^3$, so $L \le b^3 \le U$. Finally

$$ U - L = \sum 3(x_k^2 - x_{k-1}^2)\,\Delta x_k = \sum 3(x_k + x_{k-1})(\Delta x_k)^2 \le 3 \cdot 2b \cdot \mu \sum \Delta x_k = 6b^2\mu. $$

Both $S$ and $b^3$ lie between $L$ and $U$, so $|S - b^3| \le 6b^2\mu$. Given $\varepsilon > 0$, the choice $\delta = \frac{\varepsilon}{6b^2}$ works. The function $t^3$, whose derivative is $3t^2$, played the part that $5t^2$ played in the lesson.

Shared definitions used by this lesson's figures
# house kit: prepended to every essay figure after the std imports

# palette. AZURE and EMBER are the two actors, LEAF marks an answer, ROSE a problem
let PAPER = [1, 1, 1, 1]
let INK = [0.08, 0.09, 0.11, 1]
let SLATE = [0.40, 0.44, 0.50, 1]
let MIST = [0.85, 0.86, 0.88, 1]
let AZURE = [0.13, 0.42, 0.68, 1]
let EMBER = [0.89, 0.42, 0.12, 1]
let LEAF = [0.13, 0.55, 0.36, 1]
let ROSE = [0.78, 0.22, 0.24, 1]
let PLUM = [0.47, 0.30, 0.66, 1]
let GOLD = [0.85, 0.62, 0.08, 1]

background = PAPER

# an opaque pastel of col; use for fills so overlaps do not darken
let tint = |col, amount = 0.18| [
    1 - (1 - col[0]) * amount,
    1 - (1 - col[1]) * amount,
    1 - (1 - col[2]) * amount,
    1
]

# text: Cap for labels, Note for quiet labels, Math for typeset maths
let Cap = |txt, size = 0.75, col = INK| color{col} Text(txt, size, "Charter")
let Note = |txt, size = 0.65| color{SLATE} Text(txt, size, "Charter")
let Math = |tex, size = 0.9, col = INK| color{col} Tex(tex, size)

# a paper rectangle to sit behind text that crosses lines
let Plate = |pos, size| center{pos} fill{PAPER} stroke{alpha{0} PAPER, 0} Rect(size)

# shapes with fill and stroke both set, so no stray black appears
let Pt = |pos, col = INK, r = 0.075| center{pos} fill{col} stroke{col, 1} Circle(r, 48)
let Ring = |pos, col = INK, r = 0.1, w = 3| center{pos} fill{PAPER} stroke{col, w} Circle(r, 48)
let Seg = |a, b, col = INK, w = 3| stroke{col, w} Line(a, b)
let Path = |pts, col = INK, w = 3| stroke{col, w} Polyline(pts)
let Region = |pts, col| fill{col} stroke{alpha{0} col, 0} Polygon(pts)
let Outline = |pts, col = INK, w = 3| fill{alpha{0} PAPER} stroke{col, w} Polygon(pts)
let Shape = |pts, col, amount = 0.18, w = 3| fill{tint(col, amount)} stroke{col, w} Polygon(pts)
let Disc = |pos, r, col, amount = 0.18, w = 3| center{pos} fill{tint(col, amount)} stroke{col, w} Circle(r, 96)
let Box = |pos, size, col, amount = 0.18, w = 3| center{pos} fill{tint(col, amount)} stroke{col, w} Rect(size)
# a line from a to b ending in a small solid arrowhead
let Tip = |a, b, col = INK, w = 3, head = 0.17| {
    let d = normalize([b[0] - a[0], b[1] - a[1], 0])
    let n = [-d[1], d[0], 0]
    let base = [b[0] - d[0] * head, b[1] - d[1] * head, 0]
    return [
        stroke{col, w} Line(a, base),
        fill{col} stroke{col, 1} Polygon([
            b,
            [base[0] + n[0] * head * 0.42, base[1] + n[1] * head * 0.42, 0],
            [base[0] - n[0] * head * 0.42, base[1] - n[1] * head * 0.42, 0]
        ])
    ]
}

# plots. a frame is [x0, x1, y0, y1, centre, width, height]: a data window and the scene box it fills
let Frame = |x0, x1, y0, y1, c = [0, 0, 0], w = 6.4, h = 3.6| [x0, x1, y0, y1, c, w, h]
let fx = |fr, x| fr[4][0] + (x - (fr[0] + fr[1]) / 2) * fr[5] / (fr[1] - fr[0])
let fy = |fr, y| fr[4][1] + (y - (fr[2] + fr[3]) / 2) * fr[6] / (fr[3] - fr[2])
let at = |fr, x, y| [fx(fr, x), fy(fr, y), 0]

# axes through the data origin (or the nearest edge of the window), with optional names
let Axes = |fr, x_name = "", y_name = "", col = SLATE| {
    let ox = clamp(fr[0], 0, fr[1])
    let oy = clamp(fr[2], 0, fr[3])
    var parts = [
        Tip(at(fr, fr[0], oy), [fx(fr, fr[1]) + 0.25, fy(fr, oy), 0], col, 2.5, 0.15),
        Tip(at(fr, ox, fr[2]), [fx(fr, ox), fy(fr, fr[3]) + 0.25, 0], col, 2.5, 0.15)
    ]
    if (x_name != "") {
        parts .= center{[fx(fr, fr[1]) + 0.5, fy(fr, oy), 0]} Math(x_name, 0.8, col)
    }
    if (y_name != "") {
        parts .= center{[fx(fr, ox), fy(fr, fr[3]) + 0.5, 0]} Math(y_name, 0.8, col)
    }
    return parts
}

# tick marks with numbers at the listed data values
let XTicks = |fr, xs, col = SLATE, places = 0| block {
    let oy = fy(fr, clamp(fr[2], 0, fr[3]))
    for (x in xs) {
        . Seg([fx(fr, x), oy - 0.07, 0], [fx(fr, x), oy + 0.07, 0], col, 2)
        . center{[fx(fr, x), oy - 0.33, 0]} Math(to_string(x, places), 0.72, col)
    }
}
let YTicks = |fr, ys, col = SLATE, places = 0| block {
    let ox = fx(fr, clamp(fr[0], 0, fr[1]))
    for (y in ys) {
        . Seg([ox - 0.07, fy(fr, y), 0], [ox + 0.07, fy(fr, y), 0], col, 2)
        . center{[ox - 0.36, fy(fr, y), 0]} Math(to_string(y, places), 0.72, col)
    }
}

# faint grid lines at the listed data values
let GridLines = |fr, xs, ys, col = MIST| block {
    for (x in xs) {
        . Seg(at(fr, x, fr[2]), at(fr, x, fr[3]), col, 1.5)
    }
    for (y in ys) {
        . Seg(at(fr, fr[0], y), at(fr, fr[1], y), col, 1.5)
    }
}

# the graph of f over [a, b], drawn in the frame. values are clamped to the window
let Graph = |fr, f, a, b, col = AZURE, w = 4, n = 160|
    stroke{col, w} Polyline(map(sample(a, b, n), |x| at(fr, x, clamp(fr[2], f(x), fr[3]))))

# the region between the graph of f and the x axis over [a, b]
let AreaUnder = |fr, f, a, b, col = AZURE, amount = 0.2, n = 80| {
    var pts = [at(fr, a, 0)]
    for (x in sample(a, b, n)) {
        pts .= at(fr, x, clamp(fr[2], f(x), fr[3]))
    }
    pts .= at(fr, b, 0)
    return fill{tint(col, amount)} stroke{alpha{0} col, 0} Polygon(pts)
}

# the ball of lesson 1: after t seconds it is falling at 10 t meters per second
let v = |t| 10 * t
# a car whose speedometer reading wanders between 8 and 20 meters per second
let car = |t| 14 + 6 * sin(0.8 * t - 0.6)
# two layouts: a plot with a readout panel on its right, and a plot across the whole frame
let Side = |x0, x1, y0, y1| Frame(x0, x1, y0, y1, [-0.75, -0.1, 0], 4.7, 3.1)
let Wide = |x0, x1, y0, y1| Frame(x0, x1, y0, y1, [0.05, -0.1, 0], 6.2, 3.1)
# axes, numbered ticks and names; drawn after any filled regions so that it sits on top
let Ax = |fr, xs, ys, x_name, y_name, xp = 0, y_dx = 0.95| [
    Axes(fr),
    XTicks(fr, xs, SLATE, xp),
    YTicks(fr, ys),
    center{[fx(fr, fr[1]) + 0.62, fy(fr, 0), 0]} Math(x_name, 0.8, SLATE),
    center{[fx(fr, fr[0]) + y_dx, fy(fr, fr[3]) + 0.45, 0]} Note(y_name, 0.72)
]
# n equal slices of [a, b]
let Even = |a, b, n| map(range(0, n + 1), |k| a + (b - a) * k / n)
# one rectangle per slice of the partition xs. its height is f at the point a fraction
# `pick` of the way across the slice: 0 is the left end, 1 the right end
let Boxes = |fr, f, xs, pick, col, amount = 0.3, w = 2| block {
    for (k in range(0, len(xs) - 1)) {
        let h = f(xs[k] + pick * (xs[k + 1] - xs[k]))
        if (abs(h) > 0.0001) {
            . Shape([at(fr, xs[k], 0), at(fr, xs[k + 1], 0), at(fr, xs[k + 1], h), at(fr, xs[k], h)], col, amount, w)
        }
    }
}
# the Riemann sum those rectangles represent
let RSum = |f, xs, pick| sum(map(range(0, len(xs) - 1), |k| f(xs[k] + pick * (xs[k + 1] - xs[k])) * (xs[k + 1] - xs[k])))