Chapter 21
18 min read
Section 180 of 353

Applications: Exponential Growth and Decay

First-Order Differential Equations

The Question Behind the Equation

How long until this bacterial culture doubles? How old is this charred piece of wood from an ancient cave? How quickly does the dose of a drug leave your bloodstream? At first glance these look like three different questions in three different fields. They are the same equation wearing three costumes.

In every case there is a quantity y(t)y(t) that changes over time, and the rate of change dydt\frac{dy}{dt} is proportional to the quantity itself. Bacteria divide faster when there are more bacteria around. Radioactive atoms decay faster when there are more of them. A drug clears faster when there is more left in the body. The proportionality is the whole story — once we spot it, the calculus does the rest.

The one equation behind all of this

For some constant kk:

dydt=ky(t)\displaystyle \frac{dy}{dt} = k \, y(t)

With k>0k > 0 the quantity grows; with k<0k < 0 it decays. That sign flip is the only difference between a population explosion and a half-life.


The Defining Property

Before solving the ODE, stop and look at the equation itself. The right side contains yy, not tt. The slope at any moment depends only on where you are, not on what time it is. That is the fingerprint of exponential behavior.

Three equivalent ways to say the same thing

  • Differential form. dy/dt=kydy/dt = k y. The slope is proportional to the height.
  • Discrete form. Each tick of time multiplies yy by the same factor. After every step of size Δt\Delta t, the new value is (1+kΔt)(1 + k\,\Delta t) times the old value.
  • Process form. The fractional change per unit time is constant: 1ydydt=k\frac{1}{y}\frac{dy}{dt} = k. Whether yy is 1 or 1,000,000, the next instant it grows by the same percentage.

From Property to Equation

Suppose you don't remember the formula. You only remember the property: rate proportional to amount. Watch it write the equation for you. If doubling yy doubles the rate, and tripling yy triples the rate, then the rate is just a constant times yy. Call the constant kk. Done. That is dy/dt=kydy/dt = k y with no guessing.

The sign of kk is decided by the physics: births and chain reactions push k>0k > 0; cooling, radioactive decay, drug clearance, and discharge of a capacitor push k<0k < 0.


Solving the ODE from Scratch

The equation is separable: we can pull every yy to one side and every tt to the other.

  1. Start from dydt=ky\dfrac{dy}{dt} = k y.
  2. Divide by yy: 1ydy=kdt\dfrac{1}{y}\,dy = k\,dt.
  3. Integrate both sides: 1ydy=kdt\displaystyle \int \frac{1}{y}\,dy = \int k\,dt, giving lny=kt+C\ln|y| = k t + C.
  4. Exponentiate: y=ekt+C=eCekt|y| = e^{kt + C} = e^{C} \cdot e^{kt}. Absorb the constant eCe^{C} into a new constant AA.
  5. Apply the initial condition y(0)=y0y(0) = y_0: A=y0A = y_0.

The closed-form solution drops out:

y(t)  =  y0ekt\displaystyle y(t) \;=\; y_0 \, e^{k t}

Sanity check it by differentiating

ddt ⁣(y0ekt)=y0kekt=ky(t)\dfrac{d}{dt}\!\left(y_0 e^{kt}\right) = y_0 \cdot k \cdot e^{kt} = k \cdot y(t). The function's own derivative is kk times itself — exactly what the ODE demanded.


Two Faces of the Same Law

PropertyGrowth (k > 0)Decay (k < 0)
Sign of kpositivenegative
Solutiony₀ e^{kt}, blows upy₀ e^{kt}, settles to 0
Characteristic timedoubling: ln(2)/khalf-life: ln(2)/|k|
Slope at t = 0+k y₀−|k| y₀
Where it shows upbacteria, compound interest, viral spread (early phase), inflationradioactive decay, drug clearance, RC discharge, Newton's cooling toward ambient

Interactive Explorer

Drag kk, y0y_0, and the marker time tt. Watch the tangent line at the marker — its slope is always ky(t)k \cdot y(t). Flip on the log scale: the curve becomes a straight line of slope kk, the cleanest possible visual signature of exponential change.

Loading explorer…

What to play with first

  • Slide y0y_0 while keeping kk fixed: the doubling time / half-life doesn't change. It depends only on kk, never on the starting value.
  • Switch to log scale: every exponential becomes a straight line. That is how scientists eyeball whether real data is exponential at all.
  • Move the marker forward and watch the rate panel. Notice that the slope grows in proportion to the current height — that is dy/dt=kydy/dt = k y made visible.

Half-Life and Doubling Time

Both are answers to the same question: how long until yy changes by a factor of two? Solve y0ekT=2y0y_0 e^{k T} = 2 y_0 for growth, or y0ekT=y0/2y_0 e^{-k T} = y_0/2 for decay. The y0y_0 cancels and the answer falls out:

Tdouble=ln2kT1/2=ln2k\displaystyle T_{\text{double}} = \frac{\ln 2}{k} \qquad T_{1/2} = \frac{\ln 2}{|k|}

This is the magical part of exponential change: the characteristic time is intrinsic to the process and never depends on y0y_0. A drug with a 4-hour half-life takes 4 hours to fall by half whether you took 50 mg or 500 mg.

Rule of 72. Bankers approximate the doubling time under rr%-per-period growth as 72/r72/r. The trick comes from ln20.693\ln 2 \approx 0.693 and the fact that 0.6930.720.693 \approx 0.72 after rounding for per-period discrete growth. Same idea, different costume.

Worked Example: 4% Per Year

A small town has population y0=200y_0 = 200 and is growing at a continuous rate of k=0.07k = 0.07 per year. Compute the population every five years and find the doubling time. Try it on paper first, then expand the panel to see the full work.

Show step-by-step solution

Step 1. Write the ODE and its solution.

We have dydt=0.07y\frac{dy}{dt} = 0.07\,y with y(0)=200y(0) = 200. So y(t)=200e0.07ty(t) = 200\, e^{0.07\,t}.

Step 2. Evaluate at a few times.

t (yr)Computationy(t)
0200 · e^{0}200.0000
5200 · e^{0.35}283.8135
10200 · e^{0.70}402.7505
15200 · e^{1.05}571.5302
20200 · e^{1.40}811.0400

Notice the entries don't grow by a fixed amount per row — they grow by a fixed ratio. From row to row, yy is multiplied by e0.351.4191e^{0.35} \approx 1.4191. That is the multiplicative heart of exponential growth.

Step 3. Solve for the doubling time.

Set 200e0.07T=400200\, e^{0.07\,T} = 400. Divide by 200: e0.07T=2e^{0.07\,T} = 2. Take the natural log: 0.07T=ln20.07\,T = \ln 2. Divide: T=ln2/0.079.9021T = \ln 2 / 0.07 \approx 9.9021 years. Check: 200e0.079.9021=2002=400200\,e^{0.07 \cdot 9.9021} = 200 \cdot 2 = 400 ✓.

Step 4. Predict 2 doubling times ahead.

Two doublings is a multiplier of 4, so the population at t19.80t \approx 19.80 years should be near 2004=800200 \cdot 4 = 800. Our row at t=20t = 20 reads 811, so we are just past the second doubling — which the rate-of-72 intuition predicted.

Step 5. Sanity-check on the explorer above. Set y0=200y_0 = 200, k=0.07|k| = 0.07, growth mode, marker at t=10t = 10. The y-value should read 402.75\approx 402.75 and the slope panel should read 28.19\approx 28.19 (which is 0.07402.750.07 \cdot 402.75).


Application: Carbon-14 Dating

Living organisms keep a steady ratio of carbon-14 to carbon-12 with their environment. The moment they die, the supply stops and the 14C{}^{14}C they carry begins to decay with a well-measured half-life of T1/2=5730T_{1/2} = 5730 years — which fixes the decay constant k=ln2/57301.21×104k = \ln 2 / 5730 \approx 1.21 \times 10^{-4} per year.

Measure today's y/y0y/y_0, the surviving fraction. Inverting the decay law gives the age:

t  =  1kln ⁣(yy0)\displaystyle t \;=\; -\frac{1}{k}\,\ln\!\left(\frac{y}{y_0}\right)
Loading dating explorer…
Dead Sea Scrolls check. Lab measurements found about y/y076.5%y/y_0 \approx 76.5\% on parchment fibres. Plug in: t=ln(0.765)/k2,215t = -\ln(0.765)/k \approx 2{,}215 years. That matches the manuscripts' estimated age — the same ODE that describes bacteria growth dates a 2000-year-old document.

Application: Population vs Linear Growth

Quick: if a country's population grows 2%2\% per year for a century, how many people will there be? "Twice as many" sounds plausible if you think linearly — but the actual factor is e0.02100=e27.39e^{0.02 \cdot 100} = e^{2} \approx 7.39. The gap between the linear and the true exponential is the entire difference between intuition and reality.

Loading visualizer…

When the exponential model breaks

No real population grows exponentially forever. Resources run out, carrying capacity bites, and crowding slows reproduction. The exponential model is the early-time approximation. The next section in this part introduces the logistic equation, which adds one extra term and rescues the model from infinity.


Python: Building the Intuition

Before we trust the closed-form solution, let's rebuild it from the differential equation. We'll step dy=kydtdy = k y\,dt forward in a loop and watch how the discrete update converges to y0ekty_0 e^{kt} as the step size shrinks.

Hand-coded exponential simulator and ground-truth comparison
🐍growth_decay_scratch.py
1Import math

We pull in math.exp because the exact closed-form solution involves e^x. We use no numpy yet — pure Python keeps the mechanics in plain view.

EXAMPLE
math.exp(1) -> 2.718281828
3Function exponential_step

Defines one Euler step of the ODE dy/dt = k·y. Given the current population y, the growth rate k, and a small time step dt, it computes how much y should change.

4Docstring

Says explicitly which equation we are stepping. Code without intent is hard to read; this docstring locks the meaning to the ODE in the section.

5Compute the increment dy = k·y·dt

This is the defining intuition spelled out as code: the change in y over a small interval is proportional to the current y. Notice y itself appears on the right — that is the only thing that makes the growth exponential instead of linear.

EXAMPLE
y=200, k=0.07, dt=0.01 -> dy = 0.07*200*0.01 = 0.14
6Return updated y

We never overwrite y in place — we return a new value. This keeps the function pure and matches the mathematical update y_{n+1} = y_n + dy.

9Function simulate

Runs many Euler steps in a loop until we reach t_final. The output is a list of (t, y) pairs so we can later plot the trajectory or compare it to the exact answer.

11Initial state (t, y) = (0, y0)

Time starts at zero and y starts at the given initial value y0. These are the initial conditions of the ODE — without them, the equation has infinitely many solutions.

EXAMPLE
y0 = 200.0 -> we start the trajectory at the point (0, 200).
12history list

We record every step so we can later inspect or plot the full trajectory. A real simulator usually pushes (t, y) tuples like this so downstream code can iterate cleanly.

13while t < t_final

We march forward in time. The loop stops when the simulated time crosses t_final. Because dt is constant, this loop runs about t_final/dt times — so dt = 0.01 with t_final = 20 produces 2000 steps.

14One Euler step

Calls our pure step function. y becomes y + dy. The new y is bigger than the old y when k>0 (growth), smaller when k<0 (decay). The factor k·dt is the per-step fractional change.

EXAMPLE
Step 1: y = 200 + 0.14 = 200.14
15Advance time

We add dt to t after updating y. Order matters subtly here — we used the old y to compute dy, then we move t forward. Reversing the order would shift everything by one step.

16Record the pair

We append (t, y) to history so the final list reads as a sampled curve. The first entry is (0, 200); the last entry is approximately (20, 811).

17Return the trajectory

The simulator hands back the entire history. Functions that build up state and return it are easy to test — we can later run simulate(y0, 0.07, 20, 0.01) and inspect every step.

20Function closed_form

This is the analytic solution we derived in the math: y(t) = y0 · e^{kt}. We will use it as ground truth to score how good our Euler simulation is.

22Return y0 * exp(k*t)

One line, no loop. The exponential function does all the work. This is the payoff of solving the ODE on paper: at runtime you skip the entire loop.

EXAMPLE
y0=200, k=0.07, t=10 -> 200 * exp(0.7) = 200 * 2.01375 = 402.75
26Set initial value y0 = 200

We pick 200 so the worked example arithmetic stays clean. The qualitative behavior would be the same for any positive y0.

27Set rate k = 0.07

A 7%-per-unit-time growth rate. Concretely, ln(2)/0.07 ≈ 9.90, so the population doubles about every 9.9 time units.

28Set t_final = 20

Roughly two doubling times. Starting from 200, we expect to end near 800 — a useful sanity number to keep in your head while reading the output.

31Fine Euler trace dt = 0.01

A small step size makes Euler's approximation hug the true curve. 2000 steps total: slow on a human time scale but instant for the computer.

32Coarse Euler trace dt = 2.0

Same physics, but only 10 steps. Coarse Euler systematically *under-shoots* growth because it uses the current y as the slope for the whole interval — it never sees the bigger y that appears halfway through the step.

35Exact value at t = 10

200 · e^{0.7} ≈ 402.7505. This is the reference number; the next two prints will be near it.

36Index trace_fine[1000]

1000 steps of size 0.01 land us at simulated time 10.0. The pair is (10.0, y_fine). We pull out the y component.

37Index trace_coarse[5]

5 steps of size 2.0 also land us at simulated time 10.0. This y will be visibly smaller than 402.75.

39Print the exact value

Prints something like: exact y(10) = 402.7505. This is the ground truth from y0 · e^{kt}.

40Print fine Euler

You should see roughly 402.6 — very close to the exact value because dt = 0.01 is small.

41Print coarse Euler

You should see something around 376 — clearly under the truth. This shows that the *equation* is exact but the *discretization* matters. Smaller dt → smaller error.

15 lines without explanation
1import math
2
3def exponential_step(y, k, dt):
4    """One small Euler step of dy/dt = k * y."""
5    dy = k * y * dt
6    return y + dy
7
8
9def simulate(y0, k, t_final, dt):
10    """Simulate exponential growth/decay by stepping forward."""
11    t, y = 0.0, y0
12    history = [(t, y)]
13    while t < t_final:
14        y = exponential_step(y, k, dt)
15        t = t + dt
16        history.append((t, y))
17    return history
18
19
20def closed_form(y0, k, t):
21    """The exact analytic solution y(t) = y0 * e^(k t)."""
22    return y0 * math.exp(k * t)
23
24
25# y' = 0.07 y, y(0) = 200 -> 4% growth scenario but with k = 0.07
26y0 = 200.0
27k = 0.07
28t_final = 20.0
29
30# Small dt -> small error
31trace_fine = simulate(y0, k, t_final, dt=0.01)
32trace_coarse = simulate(y0, k, t_final, dt=2.0)
33
34# Compare at t = 10
35exact = closed_form(y0, k, 10.0)
36approx_fine = trace_fine[1000][1]   # 1000 * 0.01 = 10.0
37approx_coarse = trace_coarse[5][1]  # 5 * 2.0    = 10.0
38
39print(f"exact         y(10) = {exact:.4f}")
40print(f"Euler dt=0.01 y(10) = {approx_fine:.4f}")
41print(f"Euler dt=2.0  y(10) = {approx_coarse:.4f}")

The takeaway is not that Euler is the right tool — it isn't, for production work — but that the analytic answer y0ekty_0 e^{kt} is the limit of a very simple per-step rule. Solving the ODE on paper buys you a calculation that never needs the loop in the first place.


Python: Fitting k to Real Data

Often we know the model is exponential but we don't know kk. The fix is the oldest trick in applied math: take the log. The exponential model y=y0ekty = y_0 e^{kt} becomes the linear model ln(y/y0)=kt\ln(y/y_0) = k\,t. Now any straight-line method works.

Recovering the growth rate k from five measurements
🐍fit_k_from_data.py
1Import math

We need math.log for the natural logarithm and math.exp for the prediction step. log/exp are the only tools required to fit an exponential.

4samples list

A toy measurement table. Five (t, y) pairs were sampled from the same y' = 0.07·y, y(0)=200 ODE we used before — so the answer the algorithm should recover is k ≈ 0.07.

5First sample (0, 200)

Time zero with y = 200. This anchors y0 and contributes nothing to the rate estimate by itself (you cannot divide by t = 0).

6Sample at t = 2.5

y = 238.2 ≈ 200 · e^{0.07·2.5}. The ratio y/y0 = 1.191 is the multiplicative growth over 2.5 time units.

7Sample at t = 5.0

y = 283.8 ≈ 200 · e^{0.07·5}. The ratio is now 1.419 = e^{0.35}.

8Sample at t = 10

y = 402.8 ≈ 200 · e^{0.07·10}. After 10 time units we have just about doubled (recall doubling time ≈ 9.9), and indeed 402.8 / 200 ≈ 2.014.

9Sample at t = 20

y = 811 ≈ 200 · e^{0.07·20} = 200 · e^{1.4}. Two doubling times → roughly 4× the initial value, and 200 · 4 = 800.

12Pull out y0

We treat the first sample as the reference y(0). Every later estimate of k is computed relative to this anchor — so any noise on y0 propagates into every k_hat.

16estimates list

We will collect one estimate of k per non-zero time point. With four estimates we can later average them or inspect their spread — both useful for noisy data.

17Loop over samples[1:]

Skip the first sample (t = 0) and iterate over the remaining four pairs. samples[1:] unpacks into (t, y) for every row.

18Take log of the ratio

y(t) = y0 · e^{kt} → y/y0 = e^{kt} → log(y/y0) = kt. So one log call linearizes the entire problem. This is the single most important trick for fitting exponentials by hand.

EXAMPLE
log(283.8 / 200) = log(1.419) ≈ 0.35
19Divide by t to recover k

Once log(y/y0) = kt, dividing by t isolates k. With clean data every row gives the same k; with noisy data the rows disagree slightly and we average.

EXAMPLE
k_hat = log(283.8/200) / 5 = 0.35 / 5 = 0.07000
20Append to estimates

We store every k_hat so we can later average and also see how stable the estimate is across different time horizons.

21Print this row's estimate

Running this script you'll see four lines, each showing the time, the measurement, and the recovered k_hat ≈ 0.07000. Tiny differences come from the rounding in the synthetic measurements.

23Average across rows

Plain mean of all four estimates. For real data you'd usually do a proper least-squares fit on log(y/y0) vs t — but the unweighted mean is already very good when noise is small.

24Print the average

You should see k_avg ≈ 0.07000 — the algorithm recovered the true rate from the four samples.

27Predict y(15) using k_avg

Now we use the fitted k to extrapolate to a time point we never measured. y(15) = 200 · e^{0.07·15} = 200 · e^{1.05} ≈ 571.5. If the prediction matches the held-out truth, our model is doing its job.

28Print prediction vs truth

The printed value will be ~571.5, matching the exact y(15) for k = 0.07. This is the whole logic of model fitting: extract a parameter from past data, then trust it on new data.

9 lines without explanation
1import math
2
3# Suppose a lab measured y at five time points.
4samples = [
5    (0.0,  200.0),
6    (2.5,  238.2),
7    (5.0,  283.8),
8    (10.0, 402.8),
9    (20.0, 811.0),
10]
11
12y0 = samples[0][1]  # 200.0
13
14# For exponential model y(t) = y0 * e^(k t),
15# log(y/y0) = k * t. So k = (1/t) * log(y/y0).
16estimates = []
17for t, y in samples[1:]:
18    k_hat = math.log(y / y0) / t
19    estimates.append(k_hat)
20    print(f"t={t:5.2f}  y={y:8.3f}  ->  k_hat = {k_hat:.6f}")
21
22k_avg = sum(estimates) / len(estimates)
23print(f"\nAverage k from the four ratios: {k_avg:.6f}")
24
25# Sanity: predict y(15) using this k
26y_pred = y0 * math.exp(k_avg * 15.0)
27print(f"Predicted y(15) = {y_pred:.3f}  (truth ~ 571.5 for k=0.07)")

PyTorch: Recovering k by Gradient Descent

For a single parameter the log trick is overkill — but the moment the model gains structure (multiple compartments, missing data, constraints), you want autograd to do the bookkeeping. PyTorch turns the fitting problem into one familiar pattern: forward pass, log-space loss, backward pass, optimizer step.

Fitting an exponential with autograd
🐍fit_k_pytorch.py
1Import torch

PyTorch gives us tensors and autograd. Tensors behave like numpy arrays but additionally track every operation, so gradients can be computed automatically.

4Tensor t

Holds the five time stamps. Notice we never call .to(device) — for a parameter as small as a single scalar k, staying on CPU is faster than the data shuffle to the GPU.

EXAMPLE
t = tensor([0.0, 2.5, 5.0, 10.0, 20.0])
5Tensor y

Matching measurements. Both tensors have shape (5,) — one row per (t, y) sample.

6Lock y0

We treat y(0) as known so the only thing to fit is the rate k. Letting both y0 and k be learnable is a one-line change but would make the optimization landscape less convex.

9Parameter k initialised at 0.5

requires_grad=True turns this tensor into a learnable parameter. We deliberately start far from the truth (0.07) to verify that gradient descent actually moves.

EXAMPLE
k.requires_grad = True
11Adam optimizer

Adam adapts the learning rate per parameter using past gradient statistics. For this one-parameter problem any optimizer works, but lr=0.05 with Adam reaches 5-decimal accuracy in a few hundred steps.

13Loop for 400 steps

Each iteration: zero gradients, forward pass, compute loss, backward pass, optimizer step. This four-line dance is the heart of every PyTorch training script.

14zero_grad()

PyTorch *accumulates* gradients into .grad. Without this call, gradients from previous iterations would still be there and the optimizer would head in the wrong direction.

17Forward: y_hat = y0 * exp(k * t)

This is the analytic solution we derived: y(t) = y0 · e^{kt}. Because t is a tensor of shape (5,), the operation broadcasts and y_hat is also (5,). Every operation here is tracked by autograd.

EXAMPLE
k * t -> tensor([0, 1.25, 2.5, 5.0, 10.0]) if k=0.5
20Log-space MSE loss

Plain MSE would let the large measurement (811) dominate the loss. Comparing logs treats every decade equally — a factor-of-two error matters the same whether y is 200 or 800. This is the standard loss for exponential fits.

EXAMPLE
(log(811) - log(811))^2 = 0
22loss.backward()

Walks the computational graph in reverse, fills k.grad with d(loss)/d(k). Because k participates in exp(k·t), the gradient picks up factors of t — large t observations therefore push k harder.

23optimizer.step()

Updates k using its accumulated gradient and Adam's internal state. After this call, k.item() is closer to 0.07 than it was on the previous iteration.

25Periodic print

Every 50 steps we print k and the loss. Watching loss drop by orders of magnitude while k slides from 0.5 toward 0.07 is the most satisfying visualization of training in action.

26Format string

k.item() unwraps the 0-dim tensor into a Python float. loss.item() does the same for the scalar loss. The :.5f / :.6e modifiers give us readable, fixed-width output.

30Final report

After 400 steps we expect k ≈ 0.07000. If you change the random init, the lr, or the optimizer, the convergence trajectory differs but the final answer is the same — the loss landscape has one minimum and gradient descent finds it.

14 lines without explanation
1import torch
2
3# Same five synthetic samples
4t = torch.tensor([0.0, 2.5, 5.0, 10.0, 20.0])
5y = torch.tensor([200.0, 238.2, 283.8, 402.8, 811.0])
6y0_true = 200.0  # we'll lock y0 to the first measurement
7
8# Parameter to learn: k. Initialize at a clearly wrong value.
9k = torch.tensor(0.5, requires_grad=True)
10
11optimizer = torch.optim.Adam([k], lr=0.05)
12
13for step in range(400):
14    optimizer.zero_grad()
15
16    # Forward: model prediction y_hat = y0 * exp(k * t)
17    y_hat = y0_true * torch.exp(k * t)
18
19    # Mean squared error on the log to weight all decades equally
20    loss = torch.mean((torch.log(y_hat) - torch.log(y)) ** 2)
21
22    loss.backward()
23    optimizer.step()
24
25    if step % 50 == 0:
26        print(f"step {step:3d}   k = {k.item():.5f}   "
27              f"loss = {loss.item():.6e}")
28
29print(f"\nRecovered k = {k.item():.5f}  (target ~ 0.07000)")

Why this idea matters in machine learning

Gradient descent itself is an exponential-decay ODE in disguise. For a quadratic loss L(θ)=12(θθ)2L(\theta) = \tfrac{1}{2}(\theta - \theta^\ast)^2 the continuous-time gradient flow dθ/dt=(θθ)d\theta/dt = -(\theta - \theta^\ast) is literally the decay equation. The exponential convergence rate of gradient descent on convex quadratics comes directly from y0ety_0 e^{-t}. Every Adam step in this notebook is a discrete sample of an exponential trajectory toward the truth.


Common Pitfalls

  • Confusing k with a percentage. A 7% continuous growth rate is k=0.07k = 0.07, not 7. After one year the population is e0.071.0725e^{0.07} \approx 1.0725 times bigger — a tiny bit more than 7% because of compounding.
  • Forgetting the sign for decay. Write the equation as dy/dt=kydy/dt = -|k| y for decay and dy/dt=+kydy/dt = +|k| y for growth. The sign decides whether the solution falls or rises; arithmetic mistakes here turn a half-life into a doubling time.
  • Reading off the wrong axis. On a log-y plot, an exponential is a straight line and the slope of that line is kk. On a linear plot it is not the visual slope of the curve.
  • Extrapolating forever. The exponential model fits early data brilliantly and predicts late data terribly when a carrying capacity exists. Always check the residuals on log-y before trusting a long extrapolation.

Summary

  1. A quantity whose rate of change is proportional to itself satisfies dy/dt=kydy/dt = k y.
  2. The general solution is y(t)=y0ekty(t) = y_0 e^{kt} — derived by separating variables and integrating.
  3. The sign of kk distinguishes growth from decay; the magnitude sets the time scale through T=ln2/kT = \ln 2 / |k|.
  4. On a log-y plot, the exponential straightens out to a line of slope kk. This is the diagnostic test for the model.
  5. The same ODE governs bacteria, radioisotopes, drugs, capacitors, compound interest, and the early phase of viral spread. The equation is field-agnostic — only the meaning of yy and kk changes.
  6. Fitting kk to data is a one-line problem after taking logs. Autograd and gradient descent generalize the trick to richer models.
Loading comments...