Integrals and Accumulation
Antiderivatives and the definite integral as area under a curve, the basic integration rules, and adding up rates over time, such as energy from power.
From a rate to a total
Kestrel Energy's smart meters record two different things. One is power: how fast a household is using electricity at this moment, in kilowatts (kW). The other is energy: how much electricity has been used in total, in kilowatt-hours (kWh) — the number on the bill. Power is a rate; energy is the total that the rate adds up to. (Units and prefixes are on Units, Prefixes and Data Sizes.)
When the power is constant, the total is one multiplication. A heat pump that draws a steady 2 kW for 3 hours uses:
Draw that on a graph with time on the horizontal axis and power on the vertical axis, and the power is a flat line at height 2. The energy, 2 × 3, is the area of the rectangle under that line: 2 high and 3 wide. That picture is the key to this whole page.
Real power is never flat. It jumps when the kettle switches on and drops when the washing machine finishes. The energy is still the area under the power curve; the curve just has an awkward shape. Working out such an area is called integration. An integral is the total you get by adding up a quantity that changes continuously over an interval — geometrically, the area under its graph. Integration is the opposite of the derivative from Derivatives and Rates of Change: the derivative turns a total into a rate (energy readings into power), the integral turns a rate back into a total.
| Rate (what you measure) | Integrated over time gives | Unit check |
|---|---|---|
| Power in kW | Energy in kWh | kW × h = kWh |
| Throughput in Mbit/s | Data transferred in Mbit | Mbit/s × s = Mbit |
| Requests per second | Number of requests | requests/s × s = requests |
| Water flow in liters per minute | Liters of cooling water | L/min × min = L |
The area under a curve
To get a feel for curved areas, take a curve whose exact answer we will be able to check later: f(x) = x^2, from x = 0 to x = 3. The shaded region in the figure is the area we want.
Riemann sums: slicing into rectangles
Rectangles are easy, so cut the area into vertical strips and replace each strip by a rectangle. This is a Riemann sum, named after the German mathematician Bernhard Riemann: an approximation of the area under a curve by a sum of rectangle areas, each one strip wide and as high as the function somewhere in that strip. Worked out for the six strips in the figure:
- The interval from 0 to 3 is 3 wide. Six strips make each strip 3 ÷ 6 = 0.5 wide.
- The left edges of the strips are at x = 0, 0.5, 1, 1.5, 2 and 2.5.
- Each rectangle is as high as the curve at its left edge: 0² = 0, 0.5² = 0.25, 1² = 1, 1.5² = 2.25, 2² = 4 and 2.5² = 6.25.
- Add the heights: 0 + 0.25 + 1 + 2.25 + 4 + 6.25 = 13.75.
- Multiply by the common width: 13.75 × 0.5 = 6.875.
In summation notation, with n strips of width \Delta x = (b - a)/n and left edges x_i = a + i\,\Delta x, the same recipe reads:
In words: for every strip i from 0 to n - 1, take the height at its left edge times the width, and add everything up. The Greek capital delta, Δ, is the usual symbol for "a small step in". More strips means thinner slivers, so the error shrinks:
def f(x):
return x ** 2
def riemann(f, a, b, n):
width = (b - a) / n
return sum(f(a + i * width) for i in range(n)) * width # left endpoints
for n in (3, 6, 30, 300, 3000):
print(n, round(riemann(f, 0, 3, n), 4))
print("exact:", 3 ** 3 / 3)
3 5.0 6 6.875 30 8.555 300 8.9551 3000 8.9955 exact: 9.0
The sums creep up toward 9. The "exact" line uses a shortcut that the section on the fundamental theorem explains. Because x^2 rises from left to right, a left-edge rectangle is always lower than the curve, so every left sum here is too small; for a falling curve it would be too large.
The definite integral
The definite integral of f from a to b is the exact value the Riemann sums approach as the strips become infinitely thin: the signed area between the graph of f and the horizontal axis, from x = a to x = b. It is written:
Read the left side as "the integral from a to b of f of x, d x". Each symbol is a leftover of the sum it replaces: the integral sign ∫ is a stretched S for "sum", f(x) is the height, and dx stands for the infinitely thin width (and tells you which variable you integrate over). The numbers a and b at the bottom and top are the limits of integration: where the area starts and ends. For the example above:
Signed area: below the axis counts negative
Where the curve dips below the horizontal axis, f(x) is negative, so each rectangle "height × width" is negative too. The integral therefore gives a net area: the part above the axis minus the part below. A Kestrel customer with solar panels shows why that is useful. If power drawn from the grid counts as positive and power fed back counts as negative, the integral over a day is the net energy: drawn minus delivered. If the bill needs the two amounts separately, integrate the positive part and the negative part on their own.
Antiderivatives
Adding up thousands of rectangles works, but for a function given by a formula there is an exact route. It starts with an antiderivative: a function F whose derivative is f, so F'(x) = f(x). Finding one means running differentiation backwards: "which function has this as its rate of change?"
Try f(x) = x^2. Differentiating x^3 gives 3x^2, which is three times too big. So divide by 3: the derivative of \tfrac{1}{3}x^3 is \tfrac{1}{3} \cdot 3x^2 = x^2. An antiderivative of x^2 is \tfrac{1}{3}x^3.
It is not the only one. A constant has derivative 0, so \tfrac{1}{3}x^3 + 5 and \tfrac{1}{3}x^3 - 12 also have derivative x^2. All antiderivatives of a function differ by a constant, and the indefinite integral writes them all at once with an arbitrary constant C:
Indefinite means "no limits": the result is a family of functions, not a number. In the meter world, C is the reading the register already showed when you started counting: the power curve tells you how much was added, never where the counter began.
Standard antiderivatives
Each row below is a derivative rule read from right to left. You can check any row by differentiating the right-hand column.
| Function f(x) | Antiderivative F(x) (add + C) | Condition |
|---|---|---|
| k (a constant) | kx | |
| x^n | \dfrac{x^{n+1}}{n+1} | n \ne -1 |
| \dfrac{1}{x} | \ln \lvert x \rvert | x \ne 0 |
| e^x | e^x | |
| \sin x | -\cos x | x in radians |
| \cos x | \sin x | x in radians |
The power rule says: raise the exponent by one, then divide by the new exponent. It fails only for n = -1, because that would mean dividing by zero; that gap is exactly where 1/x and the natural logarithm \ln fit in (see Powers, Roots and Logarithms).
Two rules that do most of the work
Integration is linear, just like differentiation:
In words: you may integrate a sum term by term, and a constant factor may be moved outside the integral. A worked example, for f(x) = 3x^2 + 2:
- Split the sum: \int 3x^2\,dx + \int 2\,dx.
- Move the 3 out and use the power rule: 3 \cdot \tfrac{x^3}{3} = x^3.
- A constant 2 integrates to 2x.
- Add one constant for the whole result: \int (3x^2 + 2)\,dx = x^3 + 2x + C.
- Check by differentiating: the derivative of x^3 + 2x + C is 3x^2 + 2. Correct.
There is no simple product rule for integrals, unlike for derivatives. Techniques for products and nested functions exist (substitution, integration by parts), and many functions have no antiderivative that can be written as a formula at all. In IT that hardly matters: measured data has no formula anyway, and software integrates it numerically, as in the energy example below.
The fundamental theorem
Here is the link between the two halves of this page. If F is any antiderivative of f, then the area from a to b is:
This is the fundamental theorem of calculus. The intuition is the meter again. Let F(t) be the energy register at time t; its rate of change is the power f(t). Adding up the power from a to b must give what the register gained in that period: the reading at the end minus the reading at the start. The constant C does not matter here, because it cancels: (F(b) + C) - (F(a) + C) = F(b) - F(a).
Worked example: the area under x^2 from 0 to 3.
- Find an antiderivative: F(x) = x^3/3.
- Evaluate at the upper limit: F(3) = 27/3 = 9.
- Evaluate at the lower limit: F(0) = 0/3 = 0.
- Subtract: 9 - 0 = 9. The Riemann sums were indeed heading for 9.
A second one, with the function from the previous section, from 1 to 4. The square brackets with the limits attached are a common shorthand for "evaluate at the top, minus evaluate at the bottom":
With Python's Fraction the same calculation is exact,
with no rounding at all:
from fractions import Fraction
def F1(x): # antiderivative of x^2
return Fraction(x) ** 3 / 3
def F2(x): # antiderivative of 3x^2 + 2
return Fraction(x) ** 3 + 2 * Fraction(x)
print(F1(3) - F1(0))
print(F2(4) - F2(1))
print(F1(Fraction(1, 2)) - F1(0)) # area under x^2 from 0 to 1/2
9 69 1/24
The theorem also confirms the table of standard antiderivatives. The next example computes four areas twice: with the exact formula F(b) - F(a), and numerically with 10,000 thin strips (using each strip's midpoint, which is far more accurate than the left edge). The results are rounded to 6 decimals.
import math
def midpoint_sum(f, a, b, n=10_000):
width = (b - a) / n
return sum(f(a + (i + 0.5) * width) for i in range(n)) * width
checks = [
("1/x from 1 to e ", lambda x: 1 / x, 1, math.e, math.log(math.e) - math.log(1)),
("e^x from 0 to 1 ", math.exp, 0, 1, math.exp(1) - math.exp(0)),
("sin x from 0 to pi", math.sin, 0, math.pi, -math.cos(math.pi) + math.cos(0)),
("sin x from 0 to 2pi", math.sin, 0, 2 * math.pi, -math.cos(2 * math.pi) + math.cos(0)),
]
for name, f, a, b, exact in checks:
numeric = round(midpoint_sum(f, a, b), 6) + 0.0 # + 0.0 turns -0.0 into 0.0
print(f"{name}: exact {exact:.6f}, numeric {numeric:.6f}")
1/x from 1 to e : exact 1.000000, numeric 1.000000 e^x from 0 to 1 : exact 1.718282, numeric 1.718282 sin x from 0 to pi: exact 2.000000, numeric 2.000000 sin x from 0 to 2pi: exact 0.000000, numeric 0.000000
The last line is the signed area at work: from 0 to 2π the sine curve has one hump above the axis and an identical one below, so the net area is 0.
Worked example: energy from power readings
Now the real task. Joost Bakker, Kestrel's billing engineer, has a meter that reports the household's power every 15 minutes (96 readings per day). The billing system needs energy. Energy is the integral of power over time:
Read: the energy E between times t_1 and t_2 is the integral of the power P over time. There is no formula for P(t), only samples, so the area is approximated. A good method for samples is the trapezoidal rule: join neighboring readings with a straight line and add up the trapezoids underneath. Each trapezoid has the area "average of the two heights × width".
Step by step, for the hour in the figure:
- Convert the interval to the unit of the answer: 15 minutes = 0.25 hours. (Using minutes would give kW·min, a unit nobody bills in.)
- First trapezoid, 0 to 15 minutes: average height (2.0 + 2.4) ÷ 2 = 2.2 kW; area 2.2 × 0.25 = 0.55 kWh.
- Second: (2.4 + 3.1) ÷ 2 = 2.75 kW; 2.75 × 0.25 = 0.6875 kWh.
- Third: (3.1 + 2.8) ÷ 2 = 2.95 kW; 2.95 × 0.25 = 0.7375 kWh.
- Fourth: (2.8 + 2.2) ÷ 2 = 2.5 kW; 2.5 × 0.25 = 0.625 kWh.
- Add: 0.55 + 0.6875 + 0.7375 + 0.625 = 2.6 kWh.
# Power readings (kW) every 15 minutes; energy (kWh) is the area under the curve.
power = [2.0, 2.4, 3.1, 2.8, 2.2] # at 0, 15, 30, 45, 60 minutes
dt = 0.25 # hours
trapezoid = sum((a + b) / 2 * dt for a, b in zip(power, power[1:]))
left = sum(p * dt for p in power[:-1]) # each reading held for 15 minutes
print(f"trapezoid rule: {trapezoid:.3f} kWh")
print(f"left sum: {left:.3f} kWh")
print(f"average power: {trapezoid / 1.0:.3f} kW over 1 hour")
trapezoid rule: 2.600 kWh left sum: 2.575 kWh average power: 2.600 kW over 1 hour
The two methods differ by 0.025 kWh in this hour. That looks tiny, but a small bias repeated over millions of meter-hours is real money, which is why the method has to be fixed and documented. The last line shows a useful rearrangement: the average value of a function over an interval is its integral divided by the length of the interval, \frac{1}{b - a}\int_a^b f(x)\,dx. Energy divided by time is average power.
Other accumulations in IT
Anywhere a graph shows a rate over time, the area under it is a total. Tomasz Nowak, a network engineer in the NOC, sees a link utilization graph with one sample every 5 minutes. How much data crossed the link in those 30 minutes?
# Link throughput (Mbit/s), sampled every 5 minutes for half an hour
throughput = [120, 340, 410, 380, 150, 90, 60]
dt = 5 * 60 # seconds between samples
megabits = sum((a + b) / 2 * dt for a, b in zip(throughput, throughput[1:]))
print(f"{megabits:,.0f} Mbit")
print(f"{megabits / 8:,.0f} MB") # 8 bits per byte
print(f"{megabits / 8 / 1000:.2f} GB") # decimal prefixes: 1 GB = 1000 MB
438,000 Mbit 54,750 MB 54.75 GB
Notice the unit work: Mbit/s × s = Mbit, then divide by 8 for bytes. Other everyday integrals:
- Requests: the area under a "requests per second" graph is the number of requests served, useful for capacity planning and for usage-based cloud bills.
- Error budgets: an availability target of 99.9% per 30 days allows 0.1% of 43,200 minutes, or 43.2 minutes, of failure. Accumulating the "bad minutes" over the window shows how much budget is left.
- Control loops: the I in a PID controller is the integral of the error over time. A small error that persists keeps growing in the integral, until the controller corrects it (see PID control).
Areas that go on forever
Sometimes the interval has no end. An improper integral is an integral where a limit of integration is infinite (or the function becomes infinite inside the interval); it is defined as the limit of ordinary integrals with a finite end that moves further and further out. Surprisingly, an endless region can have a finite area. Worked example with f(x) = 1/x^2 from 1 to infinity:
- Write 1/x^2 as x^{-2} and use the power rule: an antiderivative is x^{-1}/(-1) = -1/x.
- Stop at a finite upper limit b: F(b) - F(1) = -1/b - (-1/1) = 1 - 1/b.
- Let b grow: 1/b shrinks toward 0, so the area approaches 1.
# Improper integral: area under 1/x^2 from 1 to infinity is 1
for upper in (10, 100, 1000, 10 ** 6):
print(upper, 1 - 1 / upper) # antiderivative -1/x evaluated from 1 to upper
10 0.9 100 0.99 1000 0.999 1000000 0.999999
Not every endless area is finite. For 1/x the antiderivative is \ln x, and \ln b - \ln 1 = \ln b keeps growing without bound: that integral diverges. The difference between 1/x and 1/x^2 looks small on a graph, but one tail adds up to a finite total and the other does not. The same question — does an endless sum settle down? — comes back for series on Sequences, Sums and Growth Rates, and improper integrals are everyday tools in probability, where the total area under a probability curve must be exactly 1.