Continuous interest with continuous deposits
- 25. March 2026
- #mathematics
Writing a savings calculator is a great programming exercise for beginners. They’re easy to implement in spreadsheets or programming languages like Python, and teach people about the power of compounding interest. In this article we’ll investigate a discretization error that such calculators often make and try to fix it.
A simple savings calculator
A simple savings calculator might look like this in Python:
interest_rate = 1.1 # 10% annual interest
saved_per_year = 10 # 10 units of money saved per year
years = 20
saved = 0
for year in range(1, years + 1):
saved = saved * interest_rate + saved_per_year
print(f"Year: {year:>2} Saved: {saved:.2f}")
Running the code produces the following output:
Year: 1 Saved: 10.00
Year: 2 Saved: 21.00
Year: 3 Saved: 33.10
...
Year: 18 Saved: 455.99
Year: 19 Saved: 511.59
Year: 20 Saved: 572.75
But there’s a simplification in this calculation which causes us to underestimate the total amount saved. Did you spot it?
The discretization error
The “error” in the script above is noticeable in the first year of the computation, so let’s focus on the first year. We assumed that one year passes before the amount saved per year is deposited into the account. In reality, it would likely be deposited monthly as the person saves money throughout the year.
The bank might pay you the interest owed monthly or yearly, but their internal computation is done every single day. Therefore depositing as early as possible (when you get your salary) will help accumulate more interest on your deposit throughout the year. The same applies to mutual funds.
If the yearly interest rate is \(r\), then the monthly interest rate is \(r^{1/12}\) and the yearly interest rate is \(r^{1/365}\). This is because interest rates compound multiplicatively, so the geometric mean, not the arithmetic mean, is the correct computation.
Back to our savings calculator: in that first year, if we deposit monthly and compute the interest monthly, we do not end up with \(10\) units of money at the end of the first year. Instead we end up with \(10.45\) units of money:
periods = 12
interest_rate = (1.1)**(1/periods)
saved_per_year = 10 / periods
saved = 0
for period in range(1, periods + 1):
saved = saved * interest_rate + saved_per_year
print(f"Period: {period:>2} Saved: {saved:.2f}")
...
Period: 12 Saved: 10.45
What happens if we compound daily (\(365\) times) instead? Or hourly (\(365 \times 12\) times)? Or every second (\(365 \times 12 \times 3600\) times)? Here is a figure showing the multiplicative factor that money grows by at the end of one year, as a function of the number of times we compound the interest, using \(r=1.1\):

For instance, if we compound \(12\) times the multiplicative factor is \(\approx 1.045\). Observe that the factor converges to a finite number instead of blowing up to infinity. We’ll show that, as we compound interest rates and deposit more and more often, the factor converges to
which for an interest rate \(r=1.1\) becomes \(0.1 / \ln(1.1) = 1.0492\) (compare with the figure above).
Continuous deposits
Let \(a\) be the total amount deposited in a year, let \(r\) be the yearly interest rate and \(n\) be the number of times interest is compounded.
- The naïve savings calculator above used \(n=1\).
- In terms of realism for a savings calculator, \(n=12\) is a good choice if salary is paid every month and then deposited.
- From the bank’s perspective, whether it’s a bank account or a mutual fund, \(n=365\) is the upper limit.
- We’re interested in what happens as \(n \to \infty\). This is optimistic because it overestimates the discrete reality, but \(n \to \infty\) is still a much better approximation of \(n=12\) than \(n=1\) (again: see the figure).
Let \(a\) be the yearly added value. We can look for a pattern as we increase the number \(n\):
These are all geometric series, and can be written as:
The pattern for a general \(n\) emerges, and (provided we assume \(r\neq 1\)) we can use the formula for a sum of a geometric series to obtain a closed-form expression:
What does this converge to as \(n \to \infty\)? It all comes down to what the denominator \(n (r^{1/n} - 1)\), since that’s the only part of the equation that depends on \(n\). The answer is \(\ln(r)\), and there are many ways to show this: L’Hôpital’s Rule and Taylor Series are both possible methods. Here’s one way that I like: one of the many definitions of the exponential function \(e^x\) is that
so then, since \(\ln(x)\) is the inverse of \(e^x\) for positive \(x\), we must have
and if we rearrange this expression and substitute \(x\) for \(r\), we discover that \(\lim_{n \to \infty} n (r^{1/n} - 1) = \ln(r)\).
The final result is that
We’re now in a position to create a more realistic savings calculator, in which money is continually deposited and interest is continually accrued:
import math
interest_rate = 1.1
saved_per_year = 10
years = 20
saved = 0
for year in range(1, years + 1):
saved = saved * interest_rate
saved += saved_per_year * (interest_rate - 1) / math.log(interest_rate)
print(f"Year: {year:>2} Saved: {saved:.2f}")
Year: 1 Saved: 10.49
Year: 2 Saved: 22.03
Year: 3 Saved: 34.73
...
Year: 18 Saved: 478.43
Year: 19 Saved: 536.76
Year: 20 Saved: 600.93
The difference is shown graphically in the animated figure below.

Solution by integration
We can obtain the same answer as above by realizing that as \(n\) becomes large we can replace the sum with a Riemann integral:
If you know the indefinite integral of \(r^x\), then it’s easy to compute
It is comforting that both approaches give identical results. Let’s look at a third approach that also leads to the same answer, but is more general and more powerful: differential equations.
Solution by differential equations
Let us summarize what we have learned so far. When we account for continuous deposits and continuous interest rates, we do not have \(a\) units of money after the first year. Instead we end up with \(a (r-1) / \ln(r)\) units of money. The factor \((r-1) / \ln(r)\) accounts for the difference between discrete yearly deposits and continuous deposits throughout the year. When \(r=1\) this factor is undefined, but if we assume \(r \neq 1\) then we get this graph:

In the figure above, I also plotted the first-order Taylor expansion around \(r \approx 1\), which is \(g(r) = 1/2 + r/2\).
The factor that “fixes” the first year, but can be applied every single year in our savings calculator. If we re-write the recursive definition into a sum, and again use the sum of a geometric series, we end up with an expression for an arbitrary year \(n\):
Perhaps the most powerful approach to studying continuous deposits and continuous interest rates is by using differential equations. Let \(M(t)\) be money as a function of time, which is now a continuous function of \(t\). Let \(r\) be the yearly interest rate and \(t\) be measured in years. Before we proceed to the general case, let us study two simple cases first:
Deposits without any interest.
Interest without any deposits.
Both deposits and interest. Above we saw that the rate of change in a bank account is driven by \(a\) as well as \(\ln(r) M(t)\). We sum these to obtain the (first order linear ordinary) differential equation
The solution to this differential equation (verify it!) is
where \(M_0 = M(0)\) is the initial money in the account. This matches our previous result perfectly, where we assumed \(M_0 = 0\).
As a final note, if \(a\) is negative and we’re depleting the account, then a relevant question is “When will we go broke?”. This amounts to solving \(M(t) = 0\) for an unknown \(t\). In the general case, let \(M(t) = M_t\), then we can solve for \(t\) to obtain:
Finally, here is an updated Python snippet that uses the function \(M(t)\).
import math
def M(t, r, a, M0):
r_power_t = math.exp(t * math.log(r))
return M0 * r_power_t + a * (r_power_t - 1) / math.log(r)
interest_rate = 1.1
saved_per_year = 10
years = 20
for year in range(1, years + 1):
saved = M(t=year, r=interest_rate, a=saved_per_year, M0=0)
print(f"Year: {year:>2} Saved: {saved:.2f}")
Summary and references
This is an example of how the first thing one might implement is not necessarily correct. I’ve taught students about geometric series, Excel and Python using this example a few times, and I was aware of the tension between computing the interest and deposit at the end of the year (which underestimates) and at the start of the year (which overestimates).
For students familiar with calculus and geometric series, working out the limit of \(n \to \infty\) is a nice problem. In the end, assuming \(n \to \infty\) is not really correct either—it probably overestimates slightly compared to the reality (which is likely \(n=12\) or so). In many cases the corrective factor of \((r - 1) / \ln (r)\) is likely worth implementing since it’s closer to the truth than the naive \(n=1\) computation. We ignored most issues related to numerical stability in this article, but in a proper implementation \(r^{(1/n)}\) and \((r-1) / \ln(r)\).
Everything can be summarized by this set of equations: one discrete difference equation and one continuous differential equation. The equations and their closed-form solutions are:
Some further reading:
- Modeling Change One Step at a Time, from Topics in Mathematical Modeling
- Differential Equations by Chasnov
- Continuous-repayment mortgage on Wikipedia
- Compound interest on Wikipedia