<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Eli Bendersky's website</title><link href="https://eli.thegreenplace.net/" rel="alternate"></link><link href="https://eli.thegreenplace.net/feeds/all.atom.xml" rel="self"></link><id>https://eli.thegreenplace.net/</id><updated>2026-10-08T02:35:03-07:00</updated><entry><title>Monte-Carlo simulations</title><link href="https://eli.thegreenplace.net/2026/monte-carlo-simulations/" rel="alternate"></link><published>2026-10-07T19:34:00-07:00</published><updated>2026-10-08T02:35:03-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2026-10-07:/2026/monte-carlo-simulations/</id><summary type="html">&lt;p&gt;Monte Carlo simulations (or &lt;em&gt;methods&lt;/em&gt;) is the technique of applying
randomness and the &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Law_of_large_numbers"&gt;Law of large numbers&lt;/a&gt;
to the solution of various scientific and engineering problems. One of its
first documented uses was by Stanislaw Ulam and John von Neumann for nuclear
weapon simulations after WWII &lt;a class="footnote-reference" href="#footnote-1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this post …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Monte Carlo simulations (or &lt;em&gt;methods&lt;/em&gt;) is the technique of applying
randomness and the &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Law_of_large_numbers"&gt;Law of large numbers&lt;/a&gt;
to the solution of various scientific and engineering problems. One of its
first documented uses was by Stanislaw Ulam and John von Neumann for nuclear
weapon simulations after WWII &lt;a class="footnote-reference" href="#footnote-1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this post I want to provide examples of some simple uses of Monte Carlo
simulations. We'll start with the classical example of calculating the value
of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/6ac47b6d7372b4087583cfd048d20f4c1571f5cf.svg" style="height: 7px;" type="image/svg+xml"&gt;\pi&lt;/object&gt; by throwing darts.&lt;/p&gt;
&lt;div class="section" id="estimating-pi"&gt;
&lt;h2&gt;Estimating pi&lt;/h2&gt;
&lt;p&gt;Suppose we take a square board and inscribe a quarter of a circle into it. We
then proceed to throw darts at the board and record whether each dart hits
inside or outside the quarter circle. Having thrown many such darts, we
calculate the ratio of the darts inside the circle to the total number thrown.&lt;/p&gt;
&lt;p&gt;Assuming our darts are distributed uniformly over the
square, by the Law of large numbers this ratio should approach the ratio of
areas of the quarter circle &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/053e24fad601a506b974712e00fd14bbb5ea3da0.svg" style="height: 15px;" type="image/svg+xml"&gt;A_{circ}&lt;/object&gt; to the full square &lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/c401d49241b6f39e05f069d7c7bade3cf32595e8.svg" style="height: 17px;" type="image/svg+xml"&gt;A_{square}&lt;/object&gt;.&lt;/p&gt;
&lt;p&gt;With a square side length of 1, we have:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/b14567bdf5801a6461d737775a3fecc53e5f2478.svg" style="height: 43px;" type="image/svg+xml"&gt;\[\frac{A_{circ}}{A_{square}}=\frac{\pi/4}{1}=\frac{\pi}{4}\]&lt;/object&gt;
&lt;p&gt;Therefore:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/2aa6dc077da492fa32af06b4e147895ad9c2fff3.svg" style="height: 37px;" type="image/svg+xml"&gt;\[\pi\approx 4\frac{\text{hits inside}}{\text{total throws}}\]&lt;/object&gt;
&lt;p&gt;Here's a visualization:&lt;/p&gt;
&lt;link rel="stylesheet" href="https://eli.thegreenplace.net/demos/pi-monte-carlo/pi-monte-carlo.css"&gt;

&lt;div class="pi-monte-carlo-wrap"&gt;
  &lt;canvas id="pi-monte-carlo-canvas" class="pi-monte-carlo-canvas" width="400" height="400" role="img"
          aria-label="Quarter circle of radius 1 inside a unit square."&gt;
    A quarter circle of radius 1 inside a unit square.
  &lt;/canvas&gt;

  &lt;div class="pi-monte-carlo-controls"&gt;
    &lt;div class="pi-monte-carlo-row"&gt;
      &lt;div class="pi-monte-carlo-slider"&gt;
        &lt;label class="pi-monte-carlo-label" for="pi-monte-carlo-samples"&gt;
          Samples &lt;output id="pi-monte-carlo-count" for="pi-monte-carlo-samples"&gt;200&lt;/output&gt;
        &lt;/label&gt;
        &lt;input id="pi-monte-carlo-samples" class="pi-monte-carlo-range" type="range" min="10" max="1000" step="1" value="200"&gt;
        &lt;div class="pi-monte-carlo-range-labels"&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;1000&lt;/span&gt;&lt;/div&gt;
      &lt;/div&gt;
      &lt;button id="pi-monte-carlo-go" class="pi-monte-carlo-button" type="button"&gt;Run&lt;/button&gt;
    &lt;/div&gt;

    &lt;p class="pi-monte-carlo-result" role="status" aria-live="polite" aria-atomic="true"&gt;
      &lt;span class="pi-monte-carlo-symbol"&gt;π&lt;/span&gt; ≈ &lt;span id="pi-monte-carlo-estimate"&gt;—&lt;/span&gt;
    &lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;script src="https://eli.thegreenplace.net/demos/pi-monte-carlo/pi-monte-carlo.js"&gt;
&lt;/script&gt;&lt;p&gt;Change the number of samples (dart throws) and click &amp;quot;Run&amp;quot; to regenerate. The
code is very simple - here's a slightly sanitized version:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;samples&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;inside&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;inCircle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inCircle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;inside&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nx"&gt;estimateValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;inside&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You'll notice that the estimate is relatively poor - even with 1000 samples - if
you click &amp;quot;Run&amp;quot; several times, some numbers will be way off mark. While this
method does estimate &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/6ac47b6d7372b4087583cfd048d20f4c1571f5cf.svg" style="height: 7px;" type="image/svg+xml"&gt;\pi&lt;/object&gt;, it's not a particularly &lt;em&gt;good&lt;/em&gt; estimate. I
find that running ~10 billion samples is necessary to estimate it to 4 digits
after the decimal with reasonable reliability.&lt;/p&gt;
&lt;p&gt;In general, for independent trials like these, the typical sampling error
decreases in proportion to &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/b916b26ab11bcac09c1d31a41bae27051ccb4477.svg" style="height: 20px;" type="image/svg+xml"&gt;1/\sqrt{N}&lt;/object&gt;, where N is the number of trials.
This means that halving the error requires four times as many samples.&lt;/p&gt;
&lt;p&gt;While the &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/6ac47b6d7372b4087583cfd048d20f4c1571f5cf.svg" style="height: 7px;" type="image/svg+xml"&gt;\pi&lt;/object&gt; estimation may seem whimsical, it's an example of an
important class of problems to which Monte Carlo simulation is applied:
numerical integration. Our simulation estimates the area
under the quarter-circle curve, which is a definite integral.&lt;/p&gt;
&lt;p&gt;Many integrals are very difficult to solve analytically, and much research has
been done in the area of numerical analysis to develop methods to calculate
integrals. Monte Carlo methods are
particularly useful for high-dimensional integrals, where other numerical
methods can become prohibitively expensive.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="combinatorial-simulation-the-game-of-set"&gt;
&lt;h2&gt;Combinatorial simulation - the game of SET&lt;/h2&gt;
&lt;p&gt;A common use of Monte Carlo methods is estimating complex combinatorial
calculations. These often don't have analytical solutions, and enumerating all
options is intractable due to the scale of the numbers involved. As an example,
let's consider &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Set_(card_game)"&gt;the game of SET&lt;/a&gt;. Each SET card has four
attributes:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Number of shapes (1, 2 or 3)&lt;/li&gt;
&lt;li&gt;Color (Red, Green or Purple)&lt;/li&gt;
&lt;li&gt;Shape type (Oval, Diamond or Squiggle)&lt;/li&gt;
&lt;li&gt;Shading (Empty, Striped or Solid)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And the goal is to find a &amp;quot;set&amp;quot; - three cards that are either all different or
all the same &lt;em&gt;for each attribute separately&lt;/em&gt;. As an example, here's
a hand with a single set; see if you can find it &lt;a class="footnote-reference" href="#footnote-2" id="footnote-reference-2"&gt;[2]&lt;/a&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/2026/one-set-hand.svg" style="width: 600px;" type="image/svg+xml"&gt;SET hand with a single set&lt;/object&gt;
&lt;p&gt;And the next hand doesn't have any sets:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/2026/no-set-hand.svg" style="width: 600px;" type="image/svg+xml"&gt;SET hand with no hands&lt;/object&gt;
&lt;p&gt;Here's a question: given a freshly shuffled SET deck, what are the odds that
the first 12 cards drawn will have no sets among them? This question is
difficult to answer without using a computer.&lt;/p&gt;
&lt;p&gt;It's easy to calculate the number of ways to deal a 12-card hand from
a deck of 81:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/098543364b030df5cdeb5293d65c28767d18356e.svg" style="height: 43px;" type="image/svg+xml"&gt;\[\binom{81}{12}=70,724,320,184,700\]&lt;/object&gt;
&lt;p&gt;But how many of these hands have no sets? Enumerating 70 trillion SET hands
and checking each one can take quite a while, and there is no straightforward
counting formula to answer this question. Some clever methods can be employed to
leverage symmetries and other mathematical properties of SET to cut down this
search space considerably. Donald Knuth himself worked on this problem and came
up with a neat program (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;setset-all&lt;/span&gt;&lt;/tt&gt; on &lt;a class="reference external" href="https://cs.stanford.edu/~knuth/programs.html"&gt;his programs page&lt;/a&gt;) that found 2,284,535,476,080
such hands. Therefore, the answer to our question is:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/16ae56c10f6d43c2cc1de509054039f6b320bc07.svg" style="height: 39px;" type="image/svg+xml"&gt;\[\frac{2,284,535,476,080}{70,724,320,184,700}\approx 0.0323\]&lt;/object&gt;
&lt;p&gt;There's a 3.23% chance that a randomly drawn hand of 12 cards from a full deck
of SET will have no set in it.&lt;/p&gt;
&lt;p&gt;Let's see how we can use a Monte Carlo simulation to answer this question
with relatively small effort, without deep knowledge of the mathematical
properties of SET that enable cutting down the search space Knuth-style.
We can use the following pseudo-code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;C = 0
run N times:
  draw a random 12-card hand from a fresh deck
  count sets in the hand
  if no sets:
    C += 1

Estimated probability = C / N
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After running 10 million simulated draws, I got an answer of 0.0323, which
matches the real answer very closely.&lt;/p&gt;
&lt;p&gt;The Monte Carlo approach lets us solve rather complicated problems in a very
simple way. Suppose we want to answer the same question for a hand of 15 cards;
this would blow up the search space considerably - there are about 100x more
ways to select 15-card hands than there are to select 12-card hands. But for
a Monte Carlo simulation, we adjust one small parameter and get a very reliable
&lt;a class="footnote-reference" href="#footnote-3" id="footnote-reference-3"&gt;[3]&lt;/a&gt; answer (about 0.00037, in case you were wondering).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="retirement-projection"&gt;
&lt;h2&gt;Retirement projection&lt;/h2&gt;
&lt;p&gt;One domain where Monte Carlo simulations are ubiquitous is projections for
retirement portfolios. Suppose someone prepares to retire with a total sum
of 1 million dollars in their portfolio; they'd like to be able to draw
$30,000 a year from the portfolio for their living expenses. Would that work?&lt;/p&gt;
&lt;p&gt;There's a large number of factors to take into account when analyzing this
question, but for simplicity let's focus on just two: portfolio return and
inflation. We can run a naive estimate, assuming average values: suppose an
average yearly portfolio return of 4%, and average yearly inflation of 2% &lt;a class="footnote-reference" href="#footnote-4" id="footnote-reference-4"&gt;[4]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let's denote our portfolio return as &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/4873d0bc2415a46014ddaa386855afdafb8bb128.svg" style="height: 12px;" type="image/svg+xml"&gt;r=0.04&lt;/object&gt;, and inflation as
&lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/7d34e41484499ddb2865f5839fa9e077168e4eaf.svg" style="height: 15px;" type="image/svg+xml"&gt;q=0.02&lt;/object&gt;. Then the real return each year is:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/a0734fd502c94279f989107fe05d3e177acf0c46.svg" style="height: 39px;" type="image/svg+xml"&gt;\[r^{\mathrm{real}}=\frac{1+r}{1+q}-1\approx0.0196\]&lt;/object&gt;
&lt;p&gt;Starting with $1,000,000, at the end of the year we'll have $1,019,600
and then draw $30,000 for living expenses &lt;a class="footnote-reference" href="#footnote-5" id="footnote-reference-5"&gt;[5]&lt;/a&gt;, ending with $989,600. If we
continue this way, the money runs out after ~55 years, which means that a
person retiring at the age of 65 should be reasonably safe, right?&lt;/p&gt;
&lt;p&gt;But this is &lt;em&gt;very simplistic&lt;/em&gt;; assuming just average returns is risky, because
they do a poor job of representing reality, and many factors have uncertainty.
For example, the sequence of returns matters a lot; a bad year (-10%) followed
by a great year (+18%) would still count as &amp;quot;4% on average&amp;quot; but produces
significantly less money than two consecutive +4% years.
Inflation is also unpredictable, and sometimes
correlated with portfolio returns; there could be bad years of high inflation and
low / volatile returns that can wreak havoc on a portfolio.&lt;/p&gt;
&lt;p&gt;As we add factors (variance in yearly draws, mixed portfolios of stocks, bonds,
real estate, life expectancy, unexpected events, changing tax laws etc.),
relying on a single average estimate becomes increasingly more fraught. This
is why Monte Carlo simulations are very popular in this domain: by drawing
from reasonable distributions based on historical data, a Monte Carlo simulation
can easily run a million different scenarios and provide estimates: for example,
what are the odds of money running out before death.&lt;/p&gt;
&lt;p&gt;Here's a useful chart from a simulation I ran:&lt;/p&gt;
&lt;img alt="Monte Carlo simulation of retirement, showing percentiles and odds of funds running out" class="align-center" src="https://eli.thegreenplace.net/images/2026/retirement-monte-carlo.png" /&gt;
&lt;p&gt;In the top chart:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The dashed line shows the constant assumptions mentioned before: what happens
when yearly return is always 4% and inflation is always 2%.&lt;/li&gt;
&lt;li&gt;The shaded blue areas demonstrate the outcomes of 1,000,000 simulations where
inflation and return numbers are drawn from reasonable normal distributions
based on historical data. We see that in 25% of the cases, all money ran out
by roughly 22 years.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the bottom chart:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;It's even easier to see how long the funds last; if we're interested in
knowing, say, what are the odds that this plan will have enough money for
30 years - the chart shows it's about 60% (since in 40% of the simulations
the funds were depleted at this point).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Looking a this simulation, under the current assumptions the plan sounds much
riskier than the average assumption makes it appear. Assuming that a 65-y.o.
person would plan for
25 years of retirement until death, the ~30% odds of not having sufficient funds
for this duration of time are sobering. Perhaps a change in plans is needed
(such as a more frugal lifestyle or securing additional funds in some way).&lt;/p&gt;
&lt;p&gt;Retirement projection is only one of may ways in which Monte Carlo simulations
are used for financial and economical applications; given the high uncertainty
of these domains, it's very difficult to plan using analytical calculations.
Company sales projections, growth projections, stock offering prices and much
more uses Monte Carlo simulations to arrive at estimates with reasonable error
bars.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="code"&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;p&gt;All the code for the explorations in this post is &lt;a class="reference external" href="https://github.com/eliben/code-for-blog/tree/main/2026/monte-carlo"&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-1" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;While these techniques were conceptually understood much earlier, it's
not surprising that their first real applications coincided with the
development of the first digital computers. As we'll see later in the
post, Monte Carlo simulations benefit from running large numbers of
trials to get reasonable accuracy.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-2" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;The answer is: three empty red diamonds, three solid purple ovals, three
striped green squiggles. Note that for each of the 4 SET attributes,
these three cards are either all the same or all different.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-3" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;For the same number of trials, this estimate has greater relative
uncertainty than the 12-card estimate, because we encounter far fewer
hands without a set.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-4" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-4"&gt;[4]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;For the examples in this post, we'll be using &lt;em&gt;real dollars&lt;/em&gt;, or today's
value of the money. We'll assume that the $30,000 yearly draw doesn't
change and will instead apply inflation to the portfolio itself.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-5" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-5"&gt;[5]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;More sophisticated simulations would let us control these parameters;
for example, are the expense funds drawn at the beginning or end of each
year, or distributed on a monthly basis?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</content><category term="misc"></category><category term="Math"></category><category term="Science"></category><category term="Rust"></category><category term="Python"></category></entry><entry><title>Summary of reading: July - September 2026</title><link href="https://eli.thegreenplace.net/2026/summary-of-reading-july-september-2026/" rel="alternate"></link><published>2026-09-30T17:05:00-07:00</published><updated>2026-10-01T12:38:41-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2026-09-30:/2026/summary-of-reading-july-september-2026/</id><summary type="html">&lt;ul class="simple"&gt;
&lt;li&gt;&amp;quot;Wuthering Heights&amp;quot; by Emily Brontë - good writing, but the protagonists are
quite something. There's barely a likable character in the whole story - they
are all either crazy, evil, stupid or a combination of these. It's also
remarkable to consider how small the world of some people in those times was …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;ul class="simple"&gt;
&lt;li&gt;&amp;quot;Wuthering Heights&amp;quot; by Emily Brontë - good writing, but the protagonists are
quite something. There's barely a likable character in the whole story - they
are all either crazy, evil, stupid or a combination of these. It's also
remarkable to consider how small the world of some people in those times was
(pre-Victorian England); whole lives spent within a tiny area, interacting
with a handful of other people. And that's for members of the nobility, not
some bumpkin on a remote farm.&lt;/li&gt;
&lt;li&gt;&amp;quot;The Pickled City: The Story of New York pickles&amp;quot; by Paul Van Ravenstein and
Monique Mulder - yes, a book about pickles, with lots of cool photos! That's
what you get while randomly browsing in the local public library while your
kids are picking out their books. All you wanted to know about the history
of pickles, with particular emphasis on NYC in the early 20th century and
the connection to Jewish immigration to that city.&lt;/li&gt;
&lt;li&gt;&amp;quot;Rebel Island: the incredible history of Taiwan&amp;quot; by Jonathan Clements - a
detailed history of Taiwan, focusing mostly on the early years (pre-modern
times). The writing is a bit academic and dry, but it's very comprehensive.
I wish the book spent more time on the modern era, though.&lt;/li&gt;
&lt;li&gt;&amp;quot;The Old Ways: A Journey on Foot&amp;quot; by Robert Macfarlane - an ode to taking
long walks (from hours to multi-day hikes). The writing is very beautiful,
but much of it feels pointless; the author describes friends and obscure
historical poets in a lot of detail which has little to do with the main
thesis of the book. I'd say the first 1/4 of the good is very good, and the
rest is unnecessary.&lt;/li&gt;
&lt;li&gt;&amp;quot;After Rain&amp;quot; by William Trevor - I'm on a quest to find additional authors
that write evocative short stories that stay with you, and Trevor was
recommended as someone to try since my current favorites are Steinbeck
and Lahiri. &amp;quot;After Rain&amp;quot; is a collection of 12 stories, mostly about love
and relationships - between partners but also parents and children; the
settings are usually in 1980s Ireland or England. Very good stories overall,
I'm glad I tried this author and should try something else by him.&lt;/li&gt;
&lt;li&gt;&amp;quot;Spoonhandle&amp;quot; by Ruth Moore - a novel about the lives of Maine natives living
through changing times, seeing their picturesque coastal area become a magnet
for &amp;quot;summer people&amp;quot; - rich vacationers from the big cities. There's no single
protagonist in the book and the writing is very warm and human. I enjoyed it.&lt;/li&gt;
&lt;li&gt;&amp;quot;The Almighty Dollar: 500 Years of the World's Most Powerful Money&amp;quot; by
Brendan Greeley - a history-oriented exploration of the importance of the
dollar in world economy, from its beginnings as the Joachimsthaler in 16th
century Bohemia and until modern times. This book has some interesting
ideas but I found it to be quite academical and not easy to digest.&lt;/li&gt;
&lt;li&gt;&amp;quot;Behave: The Biology of Humans at Our Best and Worst&amp;quot; by Robert M. Sapolsky
- the scope of this (very long) book is huge: explaining how human behavior
works starting from basic biological principles. Our understanding of the
actual biological underpinnings of behavior is so nascent, however, that
the vast majority of the book focuses on the usual things - the psychological
studies (including all the well known ones like prisoner's dilemma, the
Stanford prison experiment, etc) and comparison with other animals. Having
read several other books on this topic in the past, I haven't found much
new in this one.&lt;/li&gt;
&lt;li&gt;&amp;quot;Humorous short stories&amp;quot; by Anton Chekhov (read in Russian) - a collection of
short stories with a humorous angle. The stories are typically very short,
just 2-3 pages each, but the character building is superb. I should try
reading something longer by Chekhov.&lt;/li&gt;
&lt;li&gt;&amp;quot;Plainsong&amp;quot; by Kent Haruf - describes a year in the life of several loosely
connected people in a remote farm town in eastern Colorado. A wholesome
story, without a specific beginning or end - just the lives of ordinary
folks.&lt;/li&gt;
&lt;li&gt;&amp;quot;Behind the Beautiful Forevers: Life, Death, and Hope in a Mumbai Undercity&amp;quot;
by Katherine Boo - investigative journalism of the lives of several connected
families in Annawadi - one of Mumbai's most miserable slums - roughly from
2007 to 2010. The only thing more shocking than the squalor in which these
people live is the degree of corruption, fraud and exploitation surrounding
them. A very poignant read.&lt;/li&gt;
&lt;li&gt;&amp;quot;The Dispossessed&amp;quot; by Ursula K. Le Guin - science fiction only in the sense
of 1984; it's always amusing to examine how unambitious the futuristic vision
of some authors is. The book was written in the early 1970s, and it presents
life thousands of years in the future as one that's pretty much identical to
what it was in the early 1970s, except for close-to-speed-of-light travel. But
science is not the point of this book anyway; it's more of a political or
philosophical fiction, examining an anarchist-communist society and comparing
it to a capitalist, &amp;quot;propertarian&amp;quot; one. Overall, this book gave me very
strong vibes of the famous Soviet kids story &amp;quot;Dunno on the moon&amp;quot; (Незнайка
на Луне), which I recall reading as a kid.&lt;/li&gt;
&lt;li&gt;&amp;quot;The Lion Women of Tehran&amp;quot; by Marjan Kamali - a multi-generational novel
focusing on the life of young women in Iran from the early 1950s to the early
1980s, in the context of the various authoritarian governments of those
eras (from Mohammad Reza Pahlavi's rule to after the Islamic revolution of
1979). Nice book showing that a good story can be told without too many
unnecessary twists and classical attention-grabbing dramas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Re-reads:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&amp;quot;The Old Way: A story of the first people&amp;quot; by Elizabeth Marshall Thomas&lt;/li&gt;
&lt;li&gt;&amp;quot;Interpreter of Maladies&amp;quot; by Jhumpa Lahiri&lt;/li&gt;
&lt;li&gt;&amp;quot;Norwegian Wood&amp;quot; by Haruki Murakami&lt;/li&gt;
&lt;li&gt;&amp;quot;Cannery Row&amp;quot; by John Steinbeck&lt;/li&gt;
&lt;/ul&gt;
</content><category term="misc"></category><category term="Book reviews"></category></entry><entry><title>Rusty thoughts on "Parse, don't validate"</title><link href="https://eli.thegreenplace.net/2026/rusty-thoughts-on-parse-dont-validate/" rel="alternate"></link><published>2026-09-26T08:25:00-07:00</published><updated>2026-09-29T00:32:04-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2026-09-26:/2026/rusty-thoughts-on-parse-dont-validate/</id><summary type="html">&lt;p&gt;Like many programmers, I find Alexis King's &lt;a class="reference external" href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/"&gt;Parse, don't validate&lt;/a&gt;
article fascinating, because it gives a name to an idiom that seems familiar and
important - one I've observed and used in the past without naming it explicitly.
This post is a review of the &amp;quot;Parse, don't validate&amp;quot; pattern applied to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Like many programmers, I find Alexis King's &lt;a class="reference external" href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/"&gt;Parse, don't validate&lt;/a&gt;
article fascinating, because it gives a name to an idiom that seems familiar and
important - one I've observed and used in the past without naming it explicitly.
This post is a review of the &amp;quot;Parse, don't validate&amp;quot; pattern applied to the Rust
programming language (the original post uses Haskell). I was particularly
interested in finding educational examples of this pattern in the Rust standard
library and other well-known projects.&lt;/p&gt;
&lt;p&gt;Without repeating the original article (please read it first!), here's the
gist of it.&lt;/p&gt;
&lt;p&gt;Consider the venerable &lt;tt class="docutils literal"&gt;Vec&lt;/tt&gt;; its &lt;tt class="docutils literal"&gt;first&lt;/tt&gt; method returns &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Option&amp;lt;&amp;amp;T&amp;gt;&lt;/span&gt;&lt;/tt&gt;.
Why? Because a vector is not guaranteed to have any elements in it, so what
to do if &lt;tt class="docutils literal"&gt;first&lt;/tt&gt; is invoked on an empty one? Returning an &lt;tt class="docutils literal"&gt;Option&lt;/tt&gt; in this
case is idiomatic in Rust &lt;a class="footnote-reference" href="#footnote-1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;, with convenient syntax sugar for accepting
the result of functions that return &lt;tt class="docutils literal"&gt;Option&lt;/tt&gt; and deciding what to do next.&lt;/p&gt;
&lt;p&gt;So what's the issue?&lt;/p&gt;
&lt;p&gt;Imagine we have a function to read some configuration paths from an env var,
while enforcing the invariant that the list can't be empty:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;anyhow&lt;/span&gt;::&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ensure&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_configuration_directories&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PathBuf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;::&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CONFIG_DIRS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;could not read CONFIG_DIRS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;directories&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PathBuf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;::&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PathBuf&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ensure&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;directories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;empty CONFIG_DIRS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So far, so good. Now let's take a typical usage of this function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;config_dirs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get_configuration_directories&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;config_dirs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;initialize_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_dir&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;unreachable!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;already checked that CONFIG_DIRS is non-empty&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once &lt;tt class="docutils literal"&gt;get_configuration_directories&lt;/tt&gt; returns a successful result,
we are guaranteed that the vector isn't empty. And yet, if we want to get the
first element of this vector, we have to use the &lt;tt class="docutils literal"&gt;first&lt;/tt&gt; method that returns
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Option&amp;lt;&amp;amp;T&amp;gt;&lt;/span&gt;&lt;/tt&gt;. We are therefore forced - again - to handle a potentially
empty case (where the option is &lt;tt class="docutils literal"&gt;None&lt;/tt&gt;).&lt;/p&gt;
&lt;p&gt;As the original article states, this has a number of problems with code clarity,
potential performance implications and a ticking time bomb if the invariant
is ever changed in &lt;tt class="docutils literal"&gt;get_configuration_directories&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;The core issue is that &lt;tt class="docutils literal"&gt;Vec&lt;/tt&gt; is fundamentally a type that can be empty; we
can carry along a &amp;quot;This one can't be empty, pinky promise!&amp;quot; comment on all the
relevant code, but it's not formally checked by anything.&lt;/p&gt;
&lt;div class="section" id="a-type-for-non-empty-vector"&gt;
&lt;h2&gt;A type for &amp;quot;non-empty&amp;quot; vector&lt;/h2&gt;
&lt;p&gt;The solution is leveraging the type system to enforce a newly established
invariant. We can use a separate type for &amp;quot;a vector that cannot be empty&amp;quot;;
in fact, such types already exist in several Rust crates - for example
&lt;a class="reference external" href="https://docs.rs/nonempty/latest/nonempty/"&gt;nonempty&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;NonEmpty&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;: &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This type has no constructor that permits &amp;quot;no elements&amp;quot;; its &lt;tt class="docutils literal"&gt;new&lt;/tt&gt; takes
one element, and its &lt;tt class="docutils literal"&gt;first&lt;/tt&gt; method returns &lt;tt class="docutils literal"&gt;&amp;amp;T&lt;/tt&gt; without an &lt;tt class="docutils literal"&gt;Option&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;: &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;: &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;NonEmpty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The rest of the crate deals with making &lt;tt class="docutils literal"&gt;NonEmpty&lt;/tt&gt; behave as close as possible
to a normal &lt;tt class="docutils literal"&gt;Vec&lt;/tt&gt;, by implementing many useful traits, as well as conversions
like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NonEmpty&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NonEmpty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;: &lt;span class="nc"&gt;vec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let's see how our &lt;tt class="docutils literal"&gt;get_configuration_directories&lt;/tt&gt; function would look if it
returned a &lt;tt class="docutils literal"&gt;NonEmpty&lt;/tt&gt; instead of a plain &lt;tt class="docutils literal"&gt;Vec&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_configuration_directories&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NonEmpty&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PathBuf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;::&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CONFIG_DIRS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;could not read CONFIG_DIRS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;directories&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;::&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PathBuf&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NonEmpty&lt;/span&gt;::&lt;span class="n"&gt;from_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;bail&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CONFIG_DIRS cannot be empty&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note the use of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;NonEmpty::from_vec&lt;/span&gt;&lt;/tt&gt; here - this is where the invariant is
established. Now a successful result is &lt;tt class="docutils literal"&gt;NonEmpty&lt;/tt&gt;, not just &lt;tt class="docutils literal"&gt;Vec&lt;/tt&gt;. The
client code looks like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;config_dirs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get_configuration_directories&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;initialize_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_dirs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There's no need to check if the returned value is empty again; this is enforced
by the type system!&lt;/p&gt;
&lt;p&gt;This is where the parse vs. validate terminology of the original article comes
from. When &lt;tt class="docutils literal"&gt;get_configuration_directories&lt;/tt&gt; returned a &lt;tt class="docutils literal"&gt;Vec&lt;/tt&gt;, it simply
validated it. But when it returns a &lt;tt class="docutils literal"&gt;NonEmpty&lt;/tt&gt; - the vector is transformed
into another entity which carries additional meaning. If we treat the concept
of parsing in the most generic sense - &amp;quot;transforming data from one format to
another&amp;quot;, this fits.&lt;/p&gt;
&lt;p&gt;To mention a less artificial example, the
&lt;a class="reference external" href="https://github.com/rustcoreutils/posixutils-rs"&gt;Rust rewrite of core POSIX utilities&lt;/a&gt;
uses &lt;tt class="docutils literal"&gt;NonEmpty&lt;/tt&gt; in several places &lt;a class="footnote-reference" href="#footnote-2" id="footnote-reference-2"&gt;[2]&lt;/a&gt;. For example, when constructing a
shell pipeline:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Pipeline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;: &lt;span class="nc"&gt;NonEmpty&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;negate_status&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The command parser's code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alias_table&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;AliasTable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;ParseResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pipeline&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// pipeline = &amp;quot;!&amp;quot; command (&amp;quot;|&amp;quot; linebreak command)*&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;negate_status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match_alternatives&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CommandToken&lt;/span&gt;::&lt;span class="n"&gt;Bang&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_some&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alias_table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;NonEmpty&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A valid &lt;tt class="docutils literal"&gt;Pipeline&lt;/tt&gt; is only returned if there are some commands in the
parsed AST. Otherwise, it just returns &lt;tt class="docutils literal"&gt;None&lt;/tt&gt;. Once this is done, the client
code can use &lt;tt class="docutils literal"&gt;commands.first()&lt;/tt&gt; without having to worry about the
possibility of it returning &lt;tt class="docutils literal"&gt;None&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="gradual-parsing-and-type-refinement"&gt;
&lt;h2&gt;Gradual parsing and type refinement&lt;/h2&gt;
&lt;p&gt;A somewhat more interesting example can be found in the source code of
&lt;a class="reference external" href="https://github.com/rust-lang/rust-analyzer"&gt;rust-analyzer&lt;/a&gt;. This project
has a type that represents an absolute filesystem path:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;AbsPathBuf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Utf8PathBuf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Instead of carrying around a regular path, the absoluteness is recorded in
the type once the initial parsing and validation is done:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TryFrom&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Utf8PathBuf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AbsPathBuf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Utf8PathBuf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;try_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path_buf&lt;/span&gt;: &lt;span class="nc"&gt;Utf8PathBuf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AbsPathBuf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Utf8PathBuf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;path_buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_absolute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbsPathBuf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path_buf&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Subsequent code doesn't have to validate the the path is absolute. The type
enforces it.&lt;/p&gt;
&lt;p&gt;Note also that &lt;tt class="docutils literal"&gt;AbsPathBuf&lt;/tt&gt; wraps &lt;tt class="docutils literal"&gt;Utf8PathBuf&lt;/tt&gt;, not &lt;tt class="docutils literal"&gt;PathBuf&lt;/tt&gt;.
&lt;tt class="docutils literal"&gt;Utf8PathBuf&lt;/tt&gt; is itself a custom, &amp;quot;parsed&amp;quot; type refinement from the
&lt;a class="reference external" href="https://docs.rs/camino/latest/camino/"&gt;camino crate&lt;/a&gt;. Regular paths in the
Rust standard library aren't guaranteed to be valid UTF-8, so they cannot be
easily converted to a &lt;tt class="docutils literal"&gt;String&lt;/tt&gt; (which has to be valid UTF-8 in Rust);
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;camino::Utf8PathBuf&lt;/span&gt;&lt;/tt&gt; establishes validity on construction, and can then
be converted to a string with just:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;as_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So we have an example of gradual parsing and type refinement here:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;std::path::PathBuf

      |
      |   prove UTF-8
      |
      V

camino::Utf8PathBuf

      |
      |   prove absolute
      |
      V

rust-analyzer&amp;#39;s paths::AbsPathBuf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="non-zero-integers"&gt;
&lt;h2&gt;Non-zero integers&lt;/h2&gt;
&lt;p&gt;Rust has a generic type called &lt;a class="reference external" href="https://doc.rust-lang.org/std/num/struct.NonZero.html"&gt;NonZero&lt;/a&gt;,
to describe unsigned numeric quantities that are known to be non-zero.&lt;/p&gt;
&lt;p&gt;For example, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;thread::available_parallelism&lt;/span&gt;&lt;/tt&gt; is defined as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;available_parallelism&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NonZero&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the call is successful, it returns a &lt;tt class="docutils literal"&gt;NonZero&amp;lt;usize&amp;gt;&lt;/tt&gt;, which is like
a normal &lt;tt class="docutils literal"&gt;usize&lt;/tt&gt; with the restriction that it's not zero. Client code doesn't
have to keep checking whether the parallelism is 0 - it's enshrined in the type
system.&lt;/p&gt;
&lt;p&gt;Rust defines the &lt;a class="reference external" href="https://doc.rust-lang.org/std/primitive.u32.html#impl-Div%3CNonZero%3Cu32%3E%3E-for-u32"&gt;division operator&lt;/a&gt;
with &lt;tt class="docutils literal"&gt;NonZero&amp;lt;usize&amp;gt;&lt;/tt&gt; in the denominator as an operation that &amp;quot;cannot panic&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;NonZero&lt;/tt&gt; has an additional advantage: zero is an invalid value for the
type, so Rust can use the zero bit pattern to represent &lt;tt class="docutils literal"&gt;None&lt;/tt&gt;. Consequently,
&lt;tt class="docutils literal"&gt;Option&amp;lt;NonZeroUsize&amp;gt;&lt;/tt&gt; is &lt;a class="reference external" href="https://doc.rust-lang.org/std/option/index.html#representation"&gt;guaranteed to have the same size&lt;/a&gt; and alignment as
&lt;tt class="docutils literal"&gt;NonZeroUsize&lt;/tt&gt; itself (and as &lt;tt class="docutils literal"&gt;usize&lt;/tt&gt;). This can avoid the extra storage
that an &lt;tt class="docutils literal"&gt;Option&amp;lt;usize&amp;gt;&lt;/tt&gt; would generally require.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="parsing-json"&gt;
&lt;h2&gt;Parsing JSON&lt;/h2&gt;
&lt;p&gt;A common example of the &amp;quot;parse, don't validate&amp;quot; idiom appears in deserializing
data from a JSON string. Rust's &lt;tt class="docutils literal"&gt;serde&lt;/tt&gt; crate enables us to do the parsing,
with validated decisions encoded into the type system, e.g.:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#[derive(Debug, Deserialize)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;workers&lt;/span&gt;: &lt;span class="nc"&gt;NonZeroUsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;: &lt;span class="nc"&gt;Mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="cp"&gt;#[derive(Debug, Deserialize)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="cp"&gt;#[serde(rename_all = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;snake_case&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Mode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Fast&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Safe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then later:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;r#&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;     {&lt;/span&gt;
&lt;span class="s"&gt;         &amp;quot;name&amp;quot;: &amp;quot;compiler&amp;quot;,&lt;/span&gt;
&lt;span class="s"&gt;         &amp;quot;workers&amp;quot;: 4,&lt;/span&gt;
&lt;span class="s"&gt;         &amp;quot;mode&amp;quot;: &amp;quot;fast&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;     }&lt;/span&gt;
&lt;span class="s"&gt; &amp;quot;#&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;: &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;serde_json&lt;/span&gt;::&lt;span class="n"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There is a lot happening behind the scenes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The types of all fields are enforced (e.g. &amp;quot;name&amp;quot; cannot be an array).&lt;/li&gt;
&lt;li&gt;The &lt;tt class="docutils literal"&gt;mode&lt;/tt&gt; is validated to be one of the enum values of &lt;tt class="docutils literal"&gt;Mode&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;workers&lt;/tt&gt; is validated to be a non-zero integer, because of the
&lt;tt class="docutils literal"&gt;NonZeroUsize&lt;/tt&gt; field type.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We take code like this for granted these days, but it's still a great example
of the pattern discussed in this post. Once the parser converted &lt;tt class="docutils literal"&gt;mode&lt;/tt&gt; into
the &lt;tt class="docutils literal"&gt;Mode&lt;/tt&gt; enum, no further validation is required.&lt;/p&gt;
&lt;p&gt;In dynamic languages like Python and JS, the process is usually much more
manual. Python's &lt;tt class="docutils literal"&gt;json.loads&lt;/tt&gt; gives us a dictionary, and it's up to the user
to validate its contents. Libraries like Pydantic permit an approach closer to
Rust's, but they're not universally used.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-1" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;p class="first"&gt;Other languages - like Go or Python - don't have a dedicated &lt;tt class="docutils literal"&gt;first&lt;/tt&gt;
method or function, and instead have the programmer rely on a
runtime check that raises
some sort of exception or panic when &lt;tt class="docutils literal"&gt;lst[0]&lt;/tt&gt; is accessed on an empty
list or slice.&lt;/p&gt;
&lt;p class="last"&gt;This is not by mistakel these methods / functions were not added to
Go and Python precisely because their semantics are tricky to narrow
down without a type like &lt;tt class="docutils literal"&gt;Option&lt;/tt&gt;.&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-2" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;The project implements its own &lt;tt class="docutils literal"&gt;NonEmpty&lt;/tt&gt;, without relying on the
&lt;tt class="docutils literal"&gt;nonempty&lt;/tt&gt; crate, but all the points in this post apply.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</content><category term="misc"></category><category term="Rust"></category></entry><entry><title>Notes on discrete-time Fourier series and transform</title><link href="https://eli.thegreenplace.net/2026/notes-on-discrete-time-fourier-series-and-transform/" rel="alternate"></link><published>2026-09-19T09:39:00-07:00</published><updated>2026-09-19T16:38:42-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2026-09-19:/2026/notes-on-discrete-time-fourier-series-and-transform/</id><summary type="html">&lt;link rel="stylesheet" href="https://eli.thegreenplace.net/demos/discrete-fourier/discrete-fourier.css"&gt;&lt;p&gt;The following are my notes on discrete-time Fourier series (DTFS), as
well as the discrete-time Fourier transform (DTFT). These topics serve
as an important theoretical underpinning to the digital processing of
signals by computers using the DFT (which will be covered in a future
post).&lt;/p&gt;
&lt;p&gt;For discrete-time signals, we use …&lt;/p&gt;</summary><content type="html">&lt;link rel="stylesheet" href="https://eli.thegreenplace.net/demos/discrete-fourier/discrete-fourier.css"&gt;&lt;p&gt;The following are my notes on discrete-time Fourier series (DTFS), as
well as the discrete-time Fourier transform (DTFT). These topics serve
as an important theoretical underpinning to the digital processing of
signals by computers using the DFT (which will be covered in a future
post).&lt;/p&gt;
&lt;p&gt;For discrete-time signals, we use the square bracket notation to
denote samples: &lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt; is the n-th sample of signal
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/11f6ad8ec52a2984abaafd7c3b516503785c2072.svg" style="height: 8px;" type="image/svg+xml"&gt;x&lt;/object&gt;.&lt;/p&gt;
&lt;p&gt;We’ll say that a discrete-time (just &lt;em&gt;discrete&lt;/em&gt; from this point on, for
brevity) signal is periodic with period &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; if:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/72444fe45e23358b5515c447242702d052cf8b29.svg" style="height: 18px;" type="image/svg+xml"&gt;\[x[n]=x[n+N]\qquad\forall{n}\]&lt;/object&gt;
&lt;p&gt;When talking about &lt;a class="reference external" href="https://eli.thegreenplace.net/2026/notes-on-fourier-series/"&gt;continuous-time Fourier
series&lt;/a&gt;,
we started with real trigonometric functions and later moved to complex
exponentials. Here, we’ll just go ahead and start directly with
(discrete) complex exponentials - converting between the two
representations isn’t difficult and can be done as needed (Appendix C in
this post demonstrates it).&lt;/p&gt;
&lt;p&gt;We’ll be dealing with the following family of signals &lt;a class="footnote-reference" href="#footnote-1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/893482d035c092058c8fe74a07d0d2007b2610f0.svg" style="height: 21px;" type="image/svg+xml"&gt;\[\phi_k[n]=e^{ikw_0n}=e^{ik(2\pi/N)n}\qquad \forall k\in\mathbb{Z}\]&lt;/object&gt;
&lt;p&gt;These are discrete complex exponentials that are periodic with period N.
&lt;object class="valign-m6 latex-math" data="https://eli.thegreenplace.net/images/math/aff8cebf2b8fefea8ffbcb72636173fa560cb3c4.svg" style="height: 21px;" type="image/svg+xml"&gt;w_0=\frac{2\pi}{N}&lt;/object&gt; is the &lt;em&gt;angular frequency&lt;/em&gt;. As discussed in
Appendix A, there are only N such distinct signals, since:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/63dc5525074209448db49c6df6e21ad55681bd06.svg" style="height: 18px;" type="image/svg+xml"&gt;\[\phi_k[n]=\phi_{k+N}[n]\qquad\forall{k}\]&lt;/object&gt;
&lt;div class="section" id="coefficients-of-discrete-time-fourier-series"&gt;
&lt;h2&gt;Coefficients of discrete-time Fourier series&lt;/h2&gt;
&lt;p&gt;We’ll want to consider the representation of an arbitrary N-periodic
&lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt; by a linear combination of &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/1da2937ccce1ec5bb97b6acf3aa4c16b0600ac0a.svg" style="height: 18px;" type="image/svg+xml"&gt;\phi_k[n]&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/bc26c473be832c359f7b4113522934be90ee741f.svg" style="height: 44px;" type="image/svg+xml"&gt;\[x[n]=\sum_{k=\langle N\rangle}a_k\phi_k[n]\]&lt;/object&gt;
&lt;p&gt;The notation &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/7b3c13344886d907a02d04d04620598839f6b01f.svg" style="height: 18px;" type="image/svg+xml"&gt;k=\langle N\rangle&lt;/object&gt; means &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/13fbd79c3d390e5d6585a21e11ff5ec1970cff0c.svg" style="height: 12px;" type="image/svg+xml"&gt;k&lt;/object&gt; runs over any
sequence of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; consecutive integers. Since there are only
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; distinct signals &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/ce4de0873a5958646dce9993ddaba5d4511d8b2d.svg" style="height: 16px;" type="image/svg+xml"&gt;\phi_k&lt;/object&gt;, the order of summation
doesn’t matter - as long as all of them are used. So it could go from 0
to &lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/4f927fbfe4d5898f228630ce76e5284ed202f837.svg" style="height: 14px;" type="image/svg+xml"&gt;N-1&lt;/object&gt;, or from 1 to &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt;, or from 2 to &lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/4bbff46d5e4a2066e44932399c1db699e807cf39.svg" style="height: 14px;" type="image/svg+xml"&gt;N+1&lt;/object&gt;, and so
on. All of these orders will enumerate all distinct &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/ce4de0873a5958646dce9993ddaba5d4511d8b2d.svg" style="height: 16px;" type="image/svg+xml"&gt;\phi_k&lt;/object&gt;.&lt;/p&gt;
&lt;p&gt;Going back to our linear combination:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/60c500ee298bcca4f6a719dff3b72b2ecb114fda.svg" style="height: 44px;" type="image/svg+xml"&gt;\[x[n]=\sum_{k=\langle N\rangle}a_k\phi_k[n]=\sum_{k=\langle N\rangle}a_ke^{ikw_0n}\]&lt;/object&gt;
&lt;p&gt;This is the discrete-time Fourier series (DTFS) representation of
&lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt; and the coefficients &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/b93e6f239fad8d0444d74634490a6e0e067b8954.svg" style="height: 11px;" type="image/svg+xml"&gt;a_k&lt;/object&gt; are the Fourier series
coefficients. Note that there are no convergence issues as in the
continuous case, because we’re dealing with a finite sum.&lt;/p&gt;
&lt;p&gt;To find the coefficients &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/b93e6f239fad8d0444d74634490a6e0e067b8954.svg" style="height: 11px;" type="image/svg+xml"&gt;a_k&lt;/object&gt;, we’ll proceed in a way that’s
somewhat similar to the continuous case. Multiply both sides of the
equation above by &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/4bd537f689b1c8840838d523803661568c9fafda.svg" style="height: 16px;" type="image/svg+xml"&gt;e^{-ir(2\pi/N)n}&lt;/object&gt; and sum over &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; terms:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/3ffeb7c8c33c990b9f29376bd6f897597e3d06b4.svg" style="height: 44px;" type="image/svg+xml"&gt;\[\sum_{n=\langle N\rangle}x[n]e^{-ir(2\pi/N)n}=
\sum_{n=\langle N\rangle}\sum_{k=\langle N\rangle}a_ke^{i(k-r)(2\pi/N)n}\]&lt;/object&gt;
&lt;p&gt;Interchanging the order of summation on the right-hand side:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/9804b43fc55e5f192b10cb39e6eb9a084be50542.svg" style="height: 44px;" type="image/svg+xml"&gt;\[\sum_{n=\langle N\rangle}x[n]e^{-ir(2\pi/N)n}=
\sum_{k=\langle N\rangle}a_k\sum_{n=\langle N\rangle}e^{i(k-r)(2\pi/N)n}\]&lt;/object&gt;
&lt;p&gt;By Appendix B, the inner sum on the right-hand side is equal to
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; when &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/0fcd76904fe07394bb05ec64895cdeb8f8515a9d.svg" style="height: 18px;" type="image/svg+xml"&gt;N\mid r-k&lt;/object&gt; and to 0 otherwise. Without loss of
generality - since we iterate over &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; consecutive values - let’s
just assume this happens in our sum when &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/6bfa11b94d344c093694a5e5c0c226bd7bb67deb.svg" style="height: 12px;" type="image/svg+xml"&gt;r=k&lt;/object&gt; (and therefore
&lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/7bfafe6ba7d6a147468ce3ae51ef134705ea6190.svg" style="height: 14px;" type="image/svg+xml"&gt;r-k=0&lt;/object&gt;, which is an integer multiple of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt;).&lt;/p&gt;
&lt;p&gt;So our equation becomes:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/aeca1db09dfaab4c07ac592863fdf8918e7e205a.svg" style="height: 44px;" type="image/svg+xml"&gt;\[\sum_{n=\langle N\rangle}x[n]e^{-ir(2\pi/N)n}=a_r N\]&lt;/object&gt;
&lt;p&gt;Or:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/725df9008f33e0060b10f1f261198885af42c03f.svg" style="height: 49px;" type="image/svg+xml"&gt;\[a_r=\frac{1}{N}\sum_{n=\langle N\rangle}x[n]e^{-ir(2\pi/N)n}\]&lt;/object&gt;
&lt;p&gt;To conclude, the Fourier decomposition of a periodic discrete signal
&lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt; into periodic complex exponentials is:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/945f40a89aa021441ed20fcfa8b08f4fa7fb1ad5.svg" style="height: 138px;" type="image/svg+xml"&gt;\[\boxed{
\begin{aligned}
    x[n]&amp;amp;=\sum_{k=\langle N\rangle}a_k e^{ik(2\pi/N)n}\\
    \vspace{2pt}\\
    a_k&amp;amp;=\frac{1}{N}\sum_{n=\langle N\rangle}x[n]e^{-ik(2\pi/N)n}
\end{aligned}
}\]&lt;/object&gt;
&lt;/div&gt;
&lt;div class="section" id="example-revisiting-the-triangular-function"&gt;
&lt;h2&gt;Example: revisiting the triangular function&lt;/h2&gt;
&lt;p&gt;Let’s revisit the triangular function &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/75a7147566fd4ba98fe5d85fe008fab6d58d3968.svg" style="height: 17px;" type="image/svg+xml"&gt;t(x)&lt;/object&gt; from &lt;a class="reference external" href="https://eli.thegreenplace.net/2026/notes-on-fourier-series"&gt;the post on
Fourier
series&lt;/a&gt;.
Here, we’ll be using the following &lt;em&gt;sampled&lt;/em&gt; version:&lt;/p&gt;
&lt;div class="fourier-plot-wrap"&gt;
  &lt;canvas id="sampled-triangle" class="fourier-plot-canvas" width="760" height="510"&gt;
  Your browser does not support the HTML5 canvas tag.
  &lt;/canvas&gt;
&lt;/div&gt;&lt;p&gt;The sampling is done with 12 samples per period of 4. The spacing
between two samples is &lt;object class="valign-m6 latex-math" data="https://eli.thegreenplace.net/images/math/13b32fa8a41892c1a019dab0362e6d9d405155a2.svg" style="height: 21px;" type="image/svg+xml"&gt;\Delta x=\frac{1}{3}&lt;/object&gt;. Another way to
express it:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/8d255b5d4fbff6cfe08740d3fac99376d86cb10f.svg" style="height: 18px;" type="image/svg+xml"&gt;\[t_d[n]=t(n/3)\]&lt;/object&gt;
&lt;p&gt;Substituting this into the definition of &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/75a7147566fd4ba98fe5d85fe008fab6d58d3968.svg" style="height: 17px;" type="image/svg+xml"&gt;t(x)&lt;/object&gt;, we get:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/cb846a2c9318006c0154c8027430ff79e8dfa895.svg" style="height: 54px;" type="image/svg+xml"&gt;\[t_d[n]=
\begin{cases}
    \frac{n}{3}     &amp;amp;  0 \leq n \leq 3 \\
    2-\frac{n}{3}   &amp;amp;  3 &amp;lt; n \leq 6  \\
\end{cases}\]&lt;/object&gt;
&lt;p&gt;We then do an odd extension &lt;a class="footnote-reference" href="#footnote-2" id="footnote-reference-2"&gt;[2]&lt;/a&gt; to the range &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/bc0e87f5ff28e46cb89d0658c909161ece916b88.svg" style="height: 18px;" type="image/svg+xml"&gt;n=[6..12)&lt;/object&gt;, and
repeat it with period &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/29fc4a36d13899104899f4ab4d5c8ce2a63aba4d.svg" style="height: 12px;" type="image/svg+xml"&gt;N=12&lt;/object&gt;.&lt;/p&gt;
&lt;p&gt;Using considerations similar to the &lt;a class="reference external" href="https://eli.thegreenplace.net/2026/notes-on-fourier-series/"&gt;continuous time
case&lt;/a&gt;,
because our function is odd we just need a sine series here:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/8785494695502450d002402ca913063457868572.svg" style="height: 52px;" type="image/svg+xml"&gt;\[t_d[n]=\sum_{k=1}^{5}b_k sin\frac{k\pi n}{6}\]&lt;/object&gt;
&lt;p&gt;The five terms correspond to the five pairs of nonzero-frequency
indices; see Appendix C.&lt;/p&gt;
&lt;p&gt;And the coefficients are:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/f7d0d38c795dd2579f2f787a52e0c929362146bb.svg" style="height: 51px;" type="image/svg+xml"&gt;\[b_k=\frac{1}{6}\sum_{n=0}^{11}t_d[n]sin\frac{k\pi n}{6}\\\]&lt;/object&gt;
&lt;p&gt;We can run this sum over half the period, because the terms at &lt;img alt="n" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/d1854cae891ec7b29161ccaf79a24b00c274bdaa.png" style="height: 7px;" /&gt;
and &lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/a57fdf4a737281653331838e54c1f649f3aef0ab.svg" style="height: 13px;" type="image/svg+xml"&gt;12-n&lt;/object&gt; are equal (both &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/b2c6547bf744e9cad27f25ea4a538006b5e10df1.svg" style="height: 18px;" type="image/svg+xml"&gt;t_d[n]&lt;/object&gt; and the sine change
signs). Also, the terms at &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/bfbd617aa9bc9d5a8b0b006de9d1d45d8e688c8d.svg" style="height: 11px;" type="image/svg+xml"&gt;n=0&lt;/object&gt; and &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/fd917de64a52110443142df37dfb4c646c895ca0.svg" style="height: 12px;" type="image/svg+xml"&gt;n=6&lt;/object&gt; vanish because
&lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/e3c78f2af1b33eec6a99870e066384434b712b41.svg" style="height: 18px;" type="image/svg+xml"&gt;t_d[0]=t_d[6]=0&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/3cdf6806c737e14fb49307ffef19344a949cc809.svg" style="height: 51px;" type="image/svg+xml"&gt;\[b_k=\frac{1}{3}\sum_{n=1}^{5}t_d[n]sin\frac{k\pi n}{6}\\\]&lt;/object&gt;
&lt;p&gt;Looking at the values of &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/6c703960ebb50c648ed2886b17158571a96dd773.svg" style="height: 14px;" type="image/svg+xml"&gt;t_d&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/0cfe030d1da24fd3e0c7306c19bd6e3f5ba9437b.svg" style="height: 45px;" type="image/svg+xml"&gt;\[b_1=\frac{1}{3}\left(\frac{1}{3}sin\frac{\pi}{6}+\frac{2}{3}sin\frac{2\pi}{6}+sin\frac{3\pi}{6}+\frac{2}{3}sin\frac{4\pi}{6}+\frac{1}{3}sin\frac{\pi}{6}\right)=\frac{4+2\sqrt{3}}{9}\]&lt;/object&gt;
&lt;p&gt;We can similarly calculate all &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/3b3f66f8c1dafc487acd2b86ecf65def380b2314.svg" style="height: 15px;" type="image/svg+xml"&gt;b_k&lt;/object&gt; until &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/146fe9d1591e99d78c5be44a6b0f0afc608b0735.svg" style="height: 12px;" type="image/svg+xml"&gt;k=5&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/025a84bb16cfb0037bc990691f9c498eafc231a9.svg" style="height: 180px;" type="image/svg+xml"&gt;\[\begin{aligned}
    b_1&amp;amp;=\frac{4+2\sqrt{3}}{9}\\
    b_2&amp;amp;=0\\
    b_3&amp;amp;=-\frac{1}{9}\\
    b_4&amp;amp;=0\\
    b_5&amp;amp;=\frac{4-2\sqrt{3}}{9}\\
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;The resulting Fourier series is therefore:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/360fb6d0e15c3f648f39813083cd487a7ebc118c.svg" style="height: 40px;" type="image/svg+xml"&gt;\[t_d[n]=\frac{4+2\sqrt{3}}{9}sin\frac{\pi n}{6}-\frac{1}{9}sin\frac{\pi n}{2}+\frac{4-2\sqrt{3}}{9}sin\frac{5\pi n}{6}\]&lt;/object&gt;
&lt;p&gt;You can use the following interactive plot to explore this approximation
to the discrete triangle function &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/b2c6547bf744e9cad27f25ea4a538006b5e10df1.svg" style="height: 18px;" type="image/svg+xml"&gt;t_d[n]&lt;/object&gt;:&lt;/p&gt;
&lt;div class="fourier-plot-wrap"&gt;
&lt;canvas id="sampled-triangle-fourier" class="fourier-plot-canvas" width="760" height="510" role="img"&gt;
Your browser does not support the HTML5 canvas tag.
&lt;/canvas&gt;
&lt;div class="fourier-plot-controls"&gt;
  &lt;label class="fourier-plot-label" for="terms"&gt;Terms in the Fourier series
    &lt;select id="terms" class="fourier-plot-input"&gt;
      &lt;option value="1"&gt;1&lt;/option&gt;
      &lt;option value="2"&gt;2&lt;/option&gt;
      &lt;option value="3"&gt;3&lt;/option&gt;
    &lt;/select&gt;
  &lt;/label&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The dropdown box selects how many of the terms in the series shown above
to plot. The orange crosses show where the series’ values at the integer
indices are, and the orange line is interpolated to better visualize the
sine waves being added. Note that when all the coefficients are used,
the DTFS &lt;em&gt;exactly&lt;/em&gt; reconstructs the input signal.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="discrete-time-fourier-transform-dtft"&gt;
&lt;h2&gt;Discrete-time Fourier Transform (DTFT)&lt;/h2&gt;
&lt;p&gt;In the post on &lt;a class="reference external" href="https://eli.thegreenplace.net/2026/notes-on-the-fourier-transform/"&gt;the Fourier
Transform&lt;/a&gt;
we’ve seen how non-periodic signals can be represented in the frequency
domain by taking the Fourier series and calculating them at the limit
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/7024b94c8e1c4e174500651fed6f4034b91338e2.svg" style="height: 12px;" type="image/svg+xml"&gt;L\rightarrow\infty&lt;/object&gt;. Here, we’ll do something similar for
discrete signals.&lt;/p&gt;
&lt;p&gt;Suppose we have a non-periodic discrete signal &lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt; of finite
duration (it’s zero outside a finite range of indices). Here’s a sample
plot:&lt;/p&gt;
&lt;div class="fourier-plot-wrap"&gt;
  &lt;canvas id="sampled-triangle-single-cycle" class="fourier-plot-canvas" width="760" height="660" role="img"&gt;
  Your browser does not support the HTML5 canvas tag.
  &lt;/canvas&gt;
&lt;/div&gt;&lt;p&gt;The bottom half is &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/c6df076ab603be3c2cbc4b1d6d092e640b77e29b.svg" style="height: 18px;" type="image/svg+xml"&gt;x_N[n]&lt;/object&gt; - a periodic signal, one period
(&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt;) of which is equal to &lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt;. We choose &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/c63ae6dd4fc9f9dda66970e827d13f7c73fe841c.svg" style="height: 12px;" type="image/svg+xml"&gt;M&lt;/object&gt; large
enough that &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/4f69300aeca511bb7959f0d5aff5e33ed79f99b9.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]=0&lt;/object&gt; outside &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/506ae4d92172f3c5ce809ecedd25641313a8b1be.svg" style="height: 18px;" type="image/svg+xml"&gt;[-M,M]&lt;/object&gt; and set
&lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/7648c8206c068d4af6259b746a017a4db66b1ad3.svg" style="height: 14px;" type="image/svg+xml"&gt;N=2M+1&lt;/object&gt;.&lt;/p&gt;
&lt;p&gt;Since &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/e3c3a8503e4f75a769e8bfe1a0aacda6768f9fdc.svg" style="height: 10px;" type="image/svg+xml"&gt;x_N&lt;/object&gt; is periodic, we can represent it with DTFS &lt;a class="footnote-reference" href="#footnote-3" id="footnote-reference-3"&gt;[3]&lt;/a&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/7655e9e51d27c95ec2f109c7991133a220d036b6.svg" style="height: 116px;" type="image/svg+xml"&gt;\[\begin{aligned}
    x_N[n]&amp;amp;=\sum_{k=-M}^{M}a_k e^{ik(2\pi/N)n}\\
    a_k&amp;amp;=\frac{1}{N}\sum_{n=-M}^{M}x[n]e^{-ik(2\pi/N)n}
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;We’ll use the notation of angular frequency:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/5863471c15fd749d07460da1cd5555373a479bee.svg" style="height: 36px;" type="image/svg+xml"&gt;\[\Delta w=\frac{2\pi}{N}\qquad w_k=k\Delta w\]&lt;/object&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/d60f037fdf97691796d26081748cfc9075bae414.svg" style="height: 116px;" type="image/svg+xml"&gt;\[\begin{aligned}
    x_N[n]&amp;amp;=\sum_{k=-M}^{M}a_k e^{i w_k n}\\
    a_k&amp;amp;=\frac{1}{N}\sum_{n=-M}^{M}x[n]e^{-i w_k n}
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;Now the critical part; since &lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt; is zero outside
&lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/506ae4d92172f3c5ce809ecedd25641313a8b1be.svg" style="height: 18px;" type="image/svg+xml"&gt;[-M,M]&lt;/object&gt;, extending the summation to all integers does not change
its value:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/651bf87714366d89832fc83ad2f37727771e1ed6.svg" style="height: 50px;" type="image/svg+xml"&gt;\[a_k=\frac{1}{N}\sum_{n=-\infty}^{\infty}x[n]e^{-i w_k n}\]&lt;/object&gt;
&lt;p&gt;We’ll define the following &lt;em&gt;continuous&lt;/em&gt; function with variable
&lt;img alt="w" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/aff024fe4ab0fece4091de044c58c9ae4233383a.png" style="height: 7px;" /&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/12e943c782c2b7d52bc4af24f03889a7a390c800.svg" style="height: 50px;" type="image/svg+xml"&gt;\[X(w)=\sum_{n=-\infty}^{\infty}x[n]e^{-i w n}\]&lt;/object&gt;
&lt;p&gt;Then at points &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/3d49dd4dad59a3db42b484b5bd2c815d00f63747.svg" style="height: 10px;" type="image/svg+xml"&gt;w_k&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/2410280553643c2394bb40d31177935f81116b78.svg" style="height: 36px;" type="image/svg+xml"&gt;\[a_k=\frac{1}{N}X(w_k)\]&lt;/object&gt;
&lt;p&gt;The function &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/634ff97b7c8940e499bad1f419482d41f5985e75.svg" style="height: 18px;" type="image/svg+xml"&gt;X(w)&lt;/object&gt; is the discrete-time Fourier transform (DTFT)
of &lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt;. The inverse DTFT process reconstructs &lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt; from
&lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/634ff97b7c8940e499bad1f419482d41f5985e75.svg" style="height: 18px;" type="image/svg+xml"&gt;X(w)&lt;/object&gt;, by substituting &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/b93e6f239fad8d0444d74634490a6e0e067b8954.svg" style="height: 11px;" type="image/svg+xml"&gt;a_k&lt;/object&gt; back into the DTFS:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/3862d71c50490b1f847db8a0d6d73d3edbf1ef59.svg" style="height: 54px;" type="image/svg+xml"&gt;\[x_N[n]=\sum_{k=-M}^{M}\frac{1}{N}X(w_k) e^{i w_k n}\]&lt;/object&gt;
&lt;p&gt;By our definition of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/485c352e1532df3fe1ad52c8ac1ec6cdcefae85f.svg" style="height: 12px;" type="image/svg+xml"&gt;\Delta w&lt;/object&gt;, we have:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/03df7807d548c507c064153f90c03c9a563c0805.svg" style="height: 37px;" type="image/svg+xml"&gt;\[\frac{1}{N}=\frac{\Delta w}{2\pi}\]&lt;/object&gt;
&lt;p&gt;Therefore:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/4a8494e729e71cda8a0a755ccda0efc956b18e23.svg" style="height: 54px;" type="image/svg+xml"&gt;\[x_N[n]=\frac{1}{2\pi}\sum_{k=-M}^{M}X(w_k) e^{i w_k n}\Delta w\]&lt;/object&gt;
&lt;p&gt;Just like in the continuous case, we recognize the sum as a &lt;em&gt;Riemann
sum&lt;/em&gt;. Let &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/e25aba83bff23dbc0999183f7c3336fbbd597321.svg" style="height: 12px;" type="image/svg+xml"&gt;M\rightarrow\infty&lt;/object&gt;. The spacing &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/485c352e1532df3fe1ad52c8ac1ec6cdcefae85f.svg" style="height: 12px;" type="image/svg+xml"&gt;\Delta w&lt;/object&gt; tends
to zero, and we can rewrite the sum as an integral:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/4439fc58730a31e2dd28d6ebda63260268060e11.svg" style="height: 43px;" type="image/svg+xml"&gt;\[x[n]=\lim_{M\rightarrow\infty}x_N[n]=\frac{1}{2\pi}\int_{-\pi}^{\pi}X(w)e^{iwn}dw\]&lt;/object&gt;
&lt;p&gt;To conclude, the DTFT and inverse DTFT pair are:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/30a15dc5e03b381e24ac86dd31144dcbbe0d7687.svg" style="height: 137px;" type="image/svg+xml"&gt;\[\boxed{
    \begin{aligned}
        X(w)&amp;amp;=\sum_{n=-\infty}^{\infty}x[n]e^{-i w n}\\
        \vspace{2pt}\\
        x[n]&amp;amp;=\frac{1}{2\pi}\int_{-\pi}^{\pi}X(w)e^{iwn}dw
    \end{aligned}
}\]&lt;/object&gt;
&lt;p&gt;&lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/634ff97b7c8940e499bad1f419482d41f5985e75.svg" style="height: 18px;" type="image/svg+xml"&gt;X(w)&lt;/object&gt; is a continuous, periodic function with period
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/0833718ca4569f36e84dbdc7742eaec65e49b150.svg" style="height: 11px;" type="image/svg+xml"&gt;2\pi&lt;/object&gt;, because:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/c03a305933e7f52bce45ca16a618ebf03bf0e70c.svg" style="height: 167px;" type="image/svg+xml"&gt;\[\begin{aligned}
    X(w+2\pi)&amp;amp;=\sum_{n=-\infty}^{\infty}x[n]e^{-i (w+2\pi) n}\\
    &amp;amp;=\sum_{n=-\infty}^{\infty}x[n]e^{-i w n}e^{-i 2\pi n}\\
    &amp;amp;=\sum_{n=-\infty}^{\infty}x[n]e^{-i w n}=X(w)\\
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;Therefore, it’s enough to run the integral on any interval of length
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/0833718ca4569f36e84dbdc7742eaec65e49b150.svg" style="height: 11px;" type="image/svg+xml"&gt;2\pi&lt;/object&gt;.&lt;/p&gt;
&lt;p&gt;The DTFS and DTFT are closely related. Starting with a finite-duration
signal &lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt;, we form a periodic signal by repeating a block of
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; samples containing it. Its DTFS coefficients are equally
spaced, scaled samples of the DTFT:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/b992961b96d8a9a9826ee6a62f6b4adf636f54b2.svg" style="height: 43px;" type="image/svg+xml"&gt;\[a_k=\frac{1}{N}X\left(\frac{2\pi k}{N}\right)\]&lt;/object&gt;
&lt;p&gt;The relation is similar to the one between Fourier series and the
Fourier transform in the continuous case.&lt;/p&gt;
&lt;p&gt;The DTFT also has useful properties similar to the continuous Fourier
transform: linearity, time shifting, the convolution theorem etc, but we
won’t spend time on them here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="appendix-a-discrete-time-complex-exponentials"&gt;
&lt;h2&gt;Appendix A: Discrete-time complex exponentials&lt;/h2&gt;
&lt;p&gt;Discrete-time complex exponentials have the form &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/7fd6adcf6eb2206420843202395b5e7971111935.svg" style="height: 15px;" type="image/svg+xml"&gt;e^{iw_0n}&lt;/object&gt; where
&lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/6950ac388dc5e1d03924e0c4e7875931b7774abf.svg" style="height: 10px;" type="image/svg+xml"&gt;w_0&lt;/object&gt; is the &lt;em&gt;angular frequency&lt;/em&gt;. The discrete nature of these
functions leads to some interesting outcomes; for example, consider the
exponential with angular frequency &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/11d5a9c41c6b478b606c650d1677cd48ff4381f7.svg" style="height: 14px;" type="image/svg+xml"&gt;w_0+2\pi&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/0e8282dc16ccb8d86eb4bcc5537f678aac1825d2.svg" style="height: 17px;" type="image/svg+xml"&gt;\[e^{i(w_0+2\pi)n}=e^{iw_0n}e^{i2\pi n}=e^{iw_0n}\]&lt;/object&gt;
&lt;p&gt;Therefore, the exponential at &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/11d5a9c41c6b478b606c650d1677cd48ff4381f7.svg" style="height: 14px;" type="image/svg+xml"&gt;w_0+2\pi&lt;/object&gt; is &lt;em&gt;exactly the same&lt;/em&gt; as
the exponential at &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/6950ac388dc5e1d03924e0c4e7875931b7774abf.svg" style="height: 10px;" type="image/svg+xml"&gt;w_0&lt;/object&gt;. In considering discrete complex
exponentials, we need only choose &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/6950ac388dc5e1d03924e0c4e7875931b7774abf.svg" style="height: 10px;" type="image/svg+xml"&gt;w_0&lt;/object&gt; from a range of length
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/0833718ca4569f36e84dbdc7742eaec65e49b150.svg" style="height: 11px;" type="image/svg+xml"&gt;2\pi&lt;/object&gt;.&lt;/p&gt;
&lt;p&gt;Another interesting aspect of these functions concerns their
periodicity. In order for &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/7fd6adcf6eb2206420843202395b5e7971111935.svg" style="height: 15px;" type="image/svg+xml"&gt;e^{iw_0n}&lt;/object&gt; to be periodic with some
positive integer period &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt;, the following must hold:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/68f3400d73ba76397c3a61bc1adb9e1fdfadd26a.svg" style="height: 17px;" type="image/svg+xml"&gt;\[e^{iw_0(n+N)}=e^{iw_0n}\]&lt;/object&gt;
&lt;p&gt;In other words:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/1b3ebb4ad3d3eec0bf3cd4b699ee3c366cca4e18.svg" style="height: 16px;" type="image/svg+xml"&gt;\[e^{iw_0N}=1\]&lt;/object&gt;
&lt;p&gt;So &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/d08b73152a14ec2be0f693981bc9c49cf2d539c8.svg" style="height: 15px;" type="image/svg+xml"&gt;w_0N&lt;/object&gt; itself must be an integral multiple of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/0833718ca4569f36e84dbdc7742eaec65e49b150.svg" style="height: 11px;" type="image/svg+xml"&gt;2\pi&lt;/object&gt;. For
some integer &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/13fbd79c3d390e5d6585a21e11ff5ec1970cff0c.svg" style="height: 12px;" type="image/svg+xml"&gt;k&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/a9ac703fbfa53f089a336b9a0c160d74a3e27183.svg" style="height: 37px;" type="image/svg+xml"&gt;\[w_0N=k\cdot(2\pi)\Longrightarrow w_0=\frac{k2\pi}{N}\]&lt;/object&gt;
&lt;p&gt;For a fixed positive integer &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt;, let’s consider all complex
exponentials for which &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; is a period:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/fa894357b1a5788b91ab60893cdeb9067bc65b87.svg" style="height: 21px;" type="image/svg+xml"&gt;\[\phi_k[n]=e^{ik(2\pi/N)n}\qquad \forall k\in\mathbb{Z}\]&lt;/object&gt;
&lt;p&gt;But earlier we’ve said that all complex exponentials with angular
frequencies &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/0833718ca4569f36e84dbdc7742eaec65e49b150.svg" style="height: 11px;" type="image/svg+xml"&gt;2\pi&lt;/object&gt; apart are identical. This means that the set
above consists of only &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; distinct exponentials. We can choose
any starting &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/13fbd79c3d390e5d6585a21e11ff5ec1970cff0c.svg" style="height: 12px;" type="image/svg+xml"&gt;k&lt;/object&gt; and get distinct signals with &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/13fbd79c3d390e5d6585a21e11ff5ec1970cff0c.svg" style="height: 12px;" type="image/svg+xml"&gt;k&lt;/object&gt;,
&lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/8d2d1975719162e2210a96c3bd5bebfdf42caa9b.svg" style="height: 14px;" type="image/svg+xml"&gt;k+1&lt;/object&gt;, &lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/f61af7574246ba464c7161afc0cddb3dc1b11267.svg" style="height: 14px;" type="image/svg+xml"&gt;k+2&lt;/object&gt; and so on until &lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/cef9dc4c07e239fd0ddcc7676f56668ca0151099.svg" style="height: 14px;" type="image/svg+xml"&gt;k+N-1&lt;/object&gt;. After that, they
begin repeating: &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/1e420e19bf305c8715608dbf062a60159dfbdc2a.svg" style="height: 18px;" type="image/svg+xml"&gt;\phi_N[n]=\phi_0[n]&lt;/object&gt; and so on.&lt;/p&gt;
&lt;p&gt;All of this is very different from the continuous case, where &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/8efd86fb78a56a5145ed7739dcb00c78581c5375.svg" style="height: 11px;" type="image/svg+xml"&gt;t&lt;/object&gt;
is a real number. The signals &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/28d243e6888f4bc4a0fc32b9f7af2a2ffa7f8c89.svg" style="height: 15px;" type="image/svg+xml"&gt;e^{iw_0t}&lt;/object&gt; and
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/9075753c0861695d1e91cec2d6932e06acd4bda6.svg" style="height: 16px;" type="image/svg+xml"&gt;e^{i(w_0+2\pi)t}&lt;/object&gt; agree only at integer values of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/8efd86fb78a56a5145ed7739dcb00c78581c5375.svg" style="height: 11px;" type="image/svg+xml"&gt;t&lt;/object&gt;, so
they are distinct functions of &lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/9eae9191c02b6e7957862fc2401767c5f8b69547.svg" style="height: 13px;" type="image/svg+xml"&gt;t\in\mathbb{R}&lt;/object&gt;. Consequently, for
a fixed positive period &lt;img alt="T" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/c2c53d66948214258a26ca9ca845d7ac0c17f8e7.png" style="height: 12px;" /&gt;, the continuous-time exponentials
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/041cda9e66d700c462a028de0f417be881e8e073.svg" style="height: 16px;" type="image/svg+xml"&gt;e^{ik(2\pi/T)t}&lt;/object&gt; are distinct for every integer &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/13fbd79c3d390e5d6585a21e11ff5ec1970cff0c.svg" style="height: 12px;" type="image/svg+xml"&gt;k&lt;/object&gt;, giving
infinitely many distinct signals.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="appendix-b-sum-of-consecutive-complex-exponentials"&gt;
&lt;h2&gt;Appendix B: Sum of consecutive complex exponentials&lt;/h2&gt;
&lt;p&gt;Let’s consider the following discrete function, defined by a sum:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/33a6c380ddeed86ef34e7e6583ca60f6d0bb642f.svg" style="height: 52px;" type="image/svg+xml"&gt;\[A[k]=\sum_{n=0}^{N-1}e^{i(2\pi/N)kn}\]&lt;/object&gt;
&lt;p&gt;We’ll want to consider two cases:&lt;/p&gt;
&lt;p&gt;(1) When &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/13fbd79c3d390e5d6585a21e11ff5ec1970cff0c.svg" style="height: 12px;" type="image/svg+xml"&gt;k&lt;/object&gt; is an integer multiple of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt;: &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/e1f10f9c84c6289cd8a4279a240c098df07b22fa.svg" style="height: 12px;" type="image/svg+xml"&gt;k=rN&lt;/object&gt; for
some integer &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/4dc7c9ec434ed06502767136789763ec11d2c4b7.svg" style="height: 8px;" type="image/svg+xml"&gt;r&lt;/object&gt; (for example &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/02f5d048ae1528ddfe91661c25c64469d096dd42.svg" style="height: 12px;" type="image/svg+xml"&gt;k=0&lt;/object&gt;, &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/84b1f89229e29e995deb4370c612a9f76e24a2f7.svg" style="height: 12px;" type="image/svg+xml"&gt;k=N&lt;/object&gt;,
&lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/fec2b67cd1bb34d1d2338637374b8c4c86b0162b.svg" style="height: 14px;" type="image/svg+xml"&gt;k=-2N&lt;/object&gt; etc.)&lt;/p&gt;
&lt;p&gt;In this case, the sum becomes:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/914ae21c02d6c49cdbc4eafd92329769c87fee81.svg" style="height: 52px;" type="image/svg+xml"&gt;\[A[k]=\sum_{n=0}^{N-1}e^{i(2\pi/N)rNn}=\sum_{n=0}^{N-1}e^{i2\pi rn}\]&lt;/object&gt;
&lt;p&gt;Since both &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/4dc7c9ec434ed06502767136789763ec11d2c4b7.svg" style="height: 8px;" type="image/svg+xml"&gt;r&lt;/object&gt; and &lt;img alt="n" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/d1854cae891ec7b29161ccaf79a24b00c274bdaa.png" style="height: 7px;" /&gt; are integers, the exponent is an
integer multiple of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/d2a8e570b43fb5570c95c42925813186ac2ea038.svg" style="height: 12px;" type="image/svg+xml"&gt;2\pi i&lt;/object&gt;, so:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/118bd1b6b3654c8e6847db1fe680270692bc2108.svg" style="height: 52px;" type="image/svg+xml"&gt;\[A[k]=\sum_{n=0}^{N-1}1=N\]&lt;/object&gt;
&lt;p&gt;(2) When &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/13fbd79c3d390e5d6585a21e11ff5ec1970cff0c.svg" style="height: 12px;" type="image/svg+xml"&gt;k&lt;/object&gt; is not an integer multiple of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt;, let’s do a
variable change &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/b723abdc2defc33a8cb6711523ebb1e84e78761d.svg" style="height: 15px;" type="image/svg+xml"&gt;p=n+1&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/b7d825bbc662795d58217b17d9620f862fce599d.svg" style="height: 54px;" type="image/svg+xml"&gt;\[A[k]=\sum_{p=1}^{N}e^{i(2\pi/N)k(p-1)}\]&lt;/object&gt;
&lt;p&gt;We can now use the finite sum formula for a geometric progression with
the common ratio &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/f4dab53801ba436b1f7b4648aaeb33ba8e4415bc.svg" style="height: 16px;" type="image/svg+xml"&gt;r=e^{i(2\pi/N)k}&lt;/object&gt;; the sum is:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/c391f9689c3c8d921b2f4ef726abe50d147365b2.svg" style="height: 41px;" type="image/svg+xml"&gt;\[S_N=\frac{1-r^N}{1-r}\]&lt;/object&gt;
&lt;p&gt;Note that &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/a492f6aa77feab0fbe5517ba5401340ff9e1ada1.svg" style="height: 16px;" type="image/svg+xml"&gt;r\neq 1&lt;/object&gt; because &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/13fbd79c3d390e5d6585a21e11ff5ec1970cff0c.svg" style="height: 12px;" type="image/svg+xml"&gt;k&lt;/object&gt; is not an integer multiple
of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt;. However:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/92a7e0eade5ae2829fcb79d29b3b0562b02722a9.svg" style="height: 17px;" type="image/svg+xml"&gt;\[r^N=e^{i(2\pi/N)kN}=1\]&lt;/object&gt;
&lt;p&gt;Therefore:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/4dd7c42cdb7a4290b25a4c25fd5851d13130efb0.svg" style="height: 18px;" type="image/svg+xml"&gt;\[A[k]=S_N=0\]&lt;/object&gt;
&lt;p&gt;While these calculations demonstrate the sums from &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/bfbd617aa9bc9d5a8b0b006de9d1d45d8e688c8d.svg" style="height: 11px;" type="image/svg+xml"&gt;n=0&lt;/object&gt; to
&lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/4f927fbfe4d5898f228630ce76e5284ed202f837.svg" style="height: 14px;" type="image/svg+xml"&gt;N-1&lt;/object&gt;, they work exactly the same for any &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; consecutive
indices, because the summand is periodic in &lt;img alt="n" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/d1854cae891ec7b29161ccaf79a24b00c274bdaa.png" style="height: 7px;" /&gt; with period
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt;. Therefore:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/ee92f8136729a20230b6d99f86f4347956f5e929.svg" style="height: 57px;" type="image/svg+xml"&gt;\[A[k]=\sum_{n=\langle N\rangle}e^{i(2\pi/N)kn}=
\begin{cases}
    N      &amp;amp; N\mid k\\
    0      &amp;amp; \text{otherwise}
\end{cases}\]&lt;/object&gt;
&lt;/div&gt;
&lt;div class="section" id="appendix-c-sine-series-decomposition-of-t-d-n"&gt;
&lt;h2&gt;Appendix C: Sine series decomposition of &lt;object class="valign-m6 latex-math heading-math" data="https://eli.thegreenplace.net/images/math/b2c6547bf744e9cad27f25ea4a538006b5e10df1.svg" style="height: 27px;" type="image/svg+xml"&gt;t_d[n]&lt;/object&gt;&lt;/h2&gt;
&lt;p&gt;Using the formula for DTFS developed earlier in the post:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/dea847f17d73cf72834a3bf138cf296585600e8f.svg" style="height: 112px;" type="image/svg+xml"&gt;\[\begin{aligned}
    a_k&amp;amp;=\frac{1}{12}\sum_{n=0}^{11}t_d[n]e^{-ik(\pi/6)n}\\
    &amp;amp;=\frac{1}{12}\sum_{n=0}^{11}t_d[n]cos\frac{k\pi n}{6}-i\frac{1}{12}\sum_{n=0}^{11}t_d[n]sin\frac{k\pi n}{6}\\
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;Recall that &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/b2c6547bf744e9cad27f25ea4a538006b5e10df1.svg" style="height: 18px;" type="image/svg+xml"&gt;t_d[n]&lt;/object&gt; is odd over the full range &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/6aaa4029be956bb3225f684513bacd9d2fa721d9.svg" style="height: 18px;" type="image/svg+xml"&gt;n=[0..12)&lt;/object&gt;.
Specifically, since the cosine is an even function, we have for any
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/6b0d31c0d563223024da45691584643ac78c96e8.svg" style="height: 7px;" type="image/svg+xml"&gt;m&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/78c15be789336fccf8caf504bf0a468c65a4ba10.svg" style="height: 63px;" type="image/svg+xml"&gt;\[\begin{aligned}
    t_d[12-m]&amp;amp;=-t_d[m]\\
    cos\frac{k\pi(12-m)}{6}&amp;amp;=cos(2\pi k -\frac{k\pi m}{6})=cos\frac{k\pi m}{6}\\
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;Therefore the cosine terms cancel out throughout the period; term 1 is
the same as negative term 11, etc.&lt;/p&gt;
&lt;p&gt;We’re left with the sines:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/04810fca94f796c09eb1a479d4c33728084e1ce7.svg" style="height: 51px;" type="image/svg+xml"&gt;\[a_k=-i\frac{1}{12}\sum_{n=0}^{11}t_d[n]sin\frac{k\pi n}{6}\]&lt;/object&gt;
&lt;p&gt;All coefficients are purely imaginary. For convenience, let’s write:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/bc8a0c8832f7e8c57b624805bf57a3ab7442b335.svg" style="height: 95px;" type="image/svg+xml"&gt;\[\begin{aligned}
    b_k&amp;amp;=\frac{1}{6}\sum_{n=0}^{11}t_d[n]sin\frac{k\pi n}{6}\\
    a_k&amp;amp;=\frac{-i b_k}{2}\\
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;Let’s turn back to the Fourier reconstruction formula:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/a81d1b157290e1b6fe8f180e4d35ebccacad75a0.svg" style="height: 44px;" type="image/svg+xml"&gt;\[t_d[n]=\sum_{k=\langle N\rangle}a_k e^{ik(2\pi/N)n}\]&lt;/object&gt;
&lt;p&gt;And pair up exponentials at &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/13fbd79c3d390e5d6585a21e11ff5ec1970cff0c.svg" style="height: 12px;" type="image/svg+xml"&gt;k&lt;/object&gt; with ones at &lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/ca298a83efb32922e18a77b4656ece9aafc49f60.svg" style="height: 14px;" type="image/svg+xml"&gt;12-k&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/d3dad0787d1f52bc208ac361a75067b2e68b3d76.svg" style="height: 17px;" type="image/svg+xml"&gt;\[e^{i(12-k)\pi n/6}=e^{i2\pi n}e^{-ikn\pi/6}=e^{-ikn\pi/6}\]&lt;/object&gt;
&lt;p&gt;Also, since &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/b2c6547bf744e9cad27f25ea4a538006b5e10df1.svg" style="height: 18px;" type="image/svg+xml"&gt;t_d[n]&lt;/object&gt; are real, the conjugate of &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/b93e6f239fad8d0444d74634490a6e0e067b8954.svg" style="height: 11px;" type="image/svg+xml"&gt;a_k&lt;/object&gt; is:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/097c9b2f3444ca43f9fba1aaff3df757b70e25bd.svg" style="height: 37px;" type="image/svg+xml"&gt;\[a_{12-k}=a_k^*=\frac{ib_k}{2}\]&lt;/object&gt;
&lt;p&gt;So adding the paired exponentials with their coefficients and using
Euler’s formula:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/f2cbd4e85e6772e49d149f5412bc92e8cb990318.svg" style="height: 125px;" type="image/svg+xml"&gt;\[\begin{aligned}
    a_ke^{i k\pi n/6}+a_{12-k}e^{-i k\pi n/6}&amp;amp;=-\frac{ib_k}{2}e^{i k\pi n/6}+\frac{ib_k}{2}e^{-i k\pi n/6}\\
    &amp;amp;=b_k\frac{e^{i k\pi n/6}-e^{-i k\pi n/6}}{2i}\\
    &amp;amp;=b_k sin\frac{k\pi n}{6}
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;Therefore:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/51f6856ecd4c6d1c0a997e355ed137c78e2ea77c.svg" style="height: 52px;" type="image/svg+xml"&gt;\[t_d[n]=\sum_{k=0}^{11}a_k e^{ik(2\pi/N)n}=\sum_{k=1}^{5}b_k sin\frac{k\pi n}{6}\]&lt;/object&gt;
&lt;p&gt;We don’t include the terms at &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/02f5d048ae1528ddfe91661c25c64469d096dd42.svg" style="height: 12px;" type="image/svg+xml"&gt;k=0&lt;/object&gt; and &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/a1c10e3a8984ac438298ab152c4168f266ede25f.svg" style="height: 12px;" type="image/svg+xml"&gt;k=6&lt;/object&gt;, because
&lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/84797f94c404864332fcfec975213ee61d2442a4.svg" style="height: 14px;" type="image/svg+xml"&gt;a_0=a_6=0&lt;/object&gt; (sine of an integral multiple of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/6ac47b6d7372b4087583cfd048d20f4c1571f5cf.svg" style="height: 7px;" type="image/svg+xml"&gt;\pi&lt;/object&gt;).&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-1" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;There are a lot of symbols used in this equation. &lt;img alt="n" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/d1854cae891ec7b29161ccaf79a24b00c274bdaa.png" style="height: 7px;" /&gt; is the
&amp;quot;time&amp;quot; index of the signal &lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt; - its domain; &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/13fbd79c3d390e5d6585a21e11ff5ec1970cff0c.svg" style="height: 12px;" type="image/svg+xml"&gt;k&lt;/object&gt;
enumerates the k-th function &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/ce4de0873a5958646dce9993ddaba5d4511d8b2d.svg" style="height: 16px;" type="image/svg+xml"&gt;\phi_k&lt;/object&gt; from a family of
functions - each &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/1da2937ccce1ec5bb97b6acf3aa4c16b0600ac0a.svg" style="height: 18px;" type="image/svg+xml"&gt;\phi_k[n]&lt;/object&gt; is a function of &lt;img alt="n" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/d1854cae891ec7b29161ccaf79a24b00c274bdaa.png" style="height: 7px;" /&gt;;
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/b51a60734da64be0e618bacbea2865a8a7dcd669.svg" style="height: 12px;" type="image/svg+xml"&gt;N&lt;/object&gt; is the period; &lt;img alt="i" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/042dc4512fa3d391c5170cf3aa61e6a638f84342.png" style="height: 12px;" /&gt; is the imaginary unit.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-2" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;The odd extension may be slightly confusing because we don’t use
negative indices. But indices are arbitrary! In our case, within a
single period index &lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/d868a680affb6ad2c7e2392566b6adc4e3201dea.svg" style="height: 12px;" type="image/svg+xml"&gt;-n&lt;/object&gt; is equivalent to &lt;object class="valign-m1 latex-math" data="https://eli.thegreenplace.net/images/math/a57fdf4a737281653331838e54c1f649f3aef0ab.svg" style="height: 13px;" type="image/svg+xml"&gt;12-n&lt;/object&gt;; if we
consider one period around the halfway point of &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/fd917de64a52110443142df37dfb4c646c895ca0.svg" style="height: 12px;" type="image/svg+xml"&gt;n=6&lt;/object&gt;, it’s
easy to see that the function is indeed odd.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-3" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Note that we use &lt;object class="valign-m5 latex-math" data="https://eli.thegreenplace.net/images/math/97897883b2ac574b045db012a128c024c5a05498.svg" style="height: 18px;" type="image/svg+xml"&gt;x[n]&lt;/object&gt;, not &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/c6df076ab603be3c2cbc4b1d6d092e640b77e29b.svg" style="height: 18px;" type="image/svg+xml"&gt;x_N[n]&lt;/object&gt; in the summation
for &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/b93e6f239fad8d0444d74634490a6e0e067b8954.svg" style="height: 11px;" type="image/svg+xml"&gt;a_k&lt;/object&gt;. This is because within the chosen range they are
equal.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;script src="https://eli.thegreenplace.net/demos/discrete-fourier/sampled-triangle.js"&gt;
&lt;/script&gt;&lt;/div&gt;
</content><category term="misc"></category><category term="Math"></category></entry><entry><title>How big are factorials?</title><link href="https://eli.thegreenplace.net/2026/how-big-are-factorials/" rel="alternate"></link><published>2026-08-27T18:52:00-07:00</published><updated>2026-08-28T01:53:48-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2026-08-27:/2026/how-big-are-factorials/</id><summary type="html">&lt;p&gt;The other day, I found myself wondering how big 52! (52 factorial) is,
and that led me to ponder how these could be estimated without a
calculator or a computer.&lt;/p&gt;
&lt;p&gt;It turns out there’s some fairly interesting math behind being able to
estimate the size (number of digits) of …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The other day, I found myself wondering how big 52! (52 factorial) is,
and that led me to ponder how these could be estimated without a
calculator or a computer.&lt;/p&gt;
&lt;p&gt;It turns out there’s some fairly interesting math behind being able to
estimate the size (number of digits) of a factorial reasonably
accurately. This post will start by stating how to do the estimate, and
if you’re curious you can read on for the math background.&lt;/p&gt;
&lt;p&gt;Without further ado, the approximation is:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/59eb2eb0cd6a017bee697978a2e97c9fa116f30d.svg" style="height: 33px;" type="image/svg+xml"&gt;\[\text{number of digits in n!}\approx n\log_{10}\left(\frac{n}{e}\right)+2\]&lt;/object&gt;
&lt;p&gt;As an example, let’s use my original question, by estimating this for
52!&lt;/p&gt;
&lt;p&gt;Well, 52 divided by &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/58e6b3a414a1e090dfc6029add0f3555ccba127f.svg" style="height: 8px;" type="image/svg+xml"&gt;e&lt;/object&gt; is... 20-ish? And &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/f1a691980a18c579b07a80f022dc267c48844592.svg" style="height: 18px;" type="image/svg+xml"&gt;\log_{10}(20)&lt;/object&gt; is
about 1.3  &lt;a class="footnote-reference" href="#footnote-1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;; therefore our estimate comes out to:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/7b5a7e609d29ba3070ef9622c6a5bad2023b6b36.svg" style="height: 16px;" type="image/svg+xml"&gt;\[\text{number of digits in 52!}\approx 52\cdot 1.3 +2 \approx69\]&lt;/object&gt;
&lt;p&gt;The real answer is 68, so this is very close! In estimates like this -
when you’re dealing with enormous numbers - being off by a couple of
digits usually isn't a big deal.&lt;/p&gt;
&lt;div class="section" id="the-gamma-function"&gt;
&lt;h2&gt;The Gamma function&lt;/h2&gt;
&lt;p&gt;The Gamma function for real &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/98b4f7b1f9e3613bfd676d3fdee9cd7b3b3f2a93.svg" style="height: 11px;" type="image/svg+xml"&gt;n&amp;gt;0&lt;/object&gt; is defined &lt;a class="footnote-reference" href="#footnote-2" id="footnote-reference-2"&gt;[2]&lt;/a&gt; as:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/109727d947cc4aa18f946c15ae28ad66104bdcff.svg" style="height: 42px;" type="image/svg+xml"&gt;\[\Gamma(n)=\int_{0}^{\infty}x^{n-1}e^{-x}dx\]&lt;/object&gt;
&lt;p&gt;This integral does not have an analytic expression in the general case,
but it does have a very useful property that we can take advantage of.
Let’s see what &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/fc32a9ecba56860559f27badf2a708fc2c5deae7.svg" style="height: 18px;" type="image/svg+xml"&gt;\Gamma(n+1)&lt;/object&gt; is:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/9bd592d202d8111d6fdc0fbf839704b50599049b.svg" style="height: 42px;" type="image/svg+xml"&gt;\[\Gamma(n+1)=\int_{0}^{\infty}x^{n}e^{-x}dx\]&lt;/object&gt;
&lt;p&gt;And now use integration by parts with:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/3eb21496d2fb403b6f7872823924ea30a490feb1.svg" style="height: 16px;" type="image/svg+xml"&gt;\[u=x^n\qquad v=-e^{-x}\]&lt;/object&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/d62e697071b3ea7710fddb098a262b0bae1ce71b.svg" style="height: 15px;" type="image/svg+xml"&gt;\[du=nx^{n-1} dx\qquad dv=e^{-x}dx\]&lt;/object&gt;
&lt;p&gt;So:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/a0f606dbd3fe6e9f81c4ab06d4b189a7e8be1103.svg" style="height: 135px;" type="image/svg+xml"&gt;\[\begin{aligned}
    \Gamma(n+1)&amp;amp;=\int_{0}^{\infty}x^{n}e^{-x}dx\\
    &amp;amp;=\left. -x^n e^{-x}\right|_{0}^{\infty}-\int_{0}^{\infty}-e^{-x}n x^{n-1}dx\\
    &amp;amp;=n\int_{0}^{\infty}x^{n-1}e^{-x}dx
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;But notice that the last integral is just &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/35d22607fb899deb63a04c62af61ff2431c5f262.svg" style="height: 18px;" type="image/svg+xml"&gt;\Gamma(n)&lt;/object&gt;; therefore,
we’ve shown that:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/f7e3f3ba2cb5182564d9c347deb416e94c8b29e6.svg" style="height: 18px;" type="image/svg+xml"&gt;\[\Gamma(n+1)=n\Gamma(n)\]&lt;/object&gt;
&lt;p&gt;Let’s also calculate &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/ebf542bc1a916f216c6b0131c026b14353ce754d.svg" style="height: 18px;" type="image/svg+xml"&gt;\Gamma(1)&lt;/object&gt; - it’s a special case that has an
analytical solution:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/7acf9430cec2f479b2445cceeade7498c5acf5a9.svg" style="height: 42px;" type="image/svg+xml"&gt;\[\Gamma(1)=\int_{0}^{\infty}e^{-x}dx=\left. -e^{-x}\right|_{0}^{\infty}=1\]&lt;/object&gt;
&lt;p&gt;This helps establish an induction argument:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/ebd16ac09b430122ee665edf67086a1dec039367.svg" style="height: 119px;" type="image/svg+xml"&gt;\[\begin{aligned}
    \Gamma(2)=1\cdot\Gamma(1)&amp;amp;=1!\\
    \Gamma(3)=2\cdot\Gamma(2)&amp;amp;=2!\\
    \Gamma(4)=3\cdot\Gamma(3)&amp;amp;=3!\\
    \dots\\
    \Gamma(n+1)=n\cdot\Gamma(n)&amp;amp;=n!
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;In other words - the Gamma function is an interpolation of the factorial
over all positive reals. Here’s a plot of the Gamma function over a
small range; note that the y axis is log-scale because of the function’s
fast growth:&lt;/p&gt;
&lt;img alt="Gamma function plot" class="align-center" src="https://eli.thegreenplace.net/images/2026/gamma-cont.png" /&gt;
&lt;/div&gt;
&lt;div class="section" id="stirlings-approximation"&gt;
&lt;h2&gt;Stirling’s approximation&lt;/h2&gt;
&lt;p&gt;You may have encountered Stirling’s approximation before:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/bc7c47f7d5a66ca699c62c087c1c457644818aca.svg" style="height: 34px;" type="image/svg+xml"&gt;\[n!\approx\sqrt{2\pi n}\cdot\left(\frac{n}{e} \right)^n\]&lt;/object&gt;
&lt;p&gt;It’s a great approximation that works reasonably well even for small
&lt;img alt="n" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/d1854cae891ec7b29161ccaf79a24b00c274bdaa.png" style="height: 7px;" /&gt;. This section is a brief overview of how Stirling’s formula is
derived from the Gamma function.&lt;/p&gt;
&lt;p&gt;Taking:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/d94b8035ec807c0ed49ad2b4b8ecbf81caf29e2e.svg" style="height: 42px;" type="image/svg+xml"&gt;\[n!=\Gamma(n+1)=\int_{0}^{\infty}x^n e^{-x}dx\]&lt;/object&gt;
&lt;p&gt;We’ll start by massaging the integrand a bit:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/c7d142255dc0de29e9878332a1cf1e9de3867c73.svg" style="height: 42px;" type="image/svg+xml"&gt;\[n!=\int_{0}^{\infty}x^n e^{-x}dx=\int_{0}^{\infty}e^{n \ln x} e^{-x}dx\]&lt;/object&gt;
&lt;p&gt;And making a change of variables &lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/c159eefe7e6d315a418f73bf57fd0f9cbcf0b3dc.svg" style="height: 11px;" type="image/svg+xml"&gt;x=ny&lt;/object&gt;, which means that
&lt;object class="valign-m3 latex-math" data="https://eli.thegreenplace.net/images/math/5b2052842a93a4eb71ea0a3e0d136d255aaed48e.svg" style="height: 16px;" type="image/svg+xml"&gt;dx=ndy&lt;/object&gt;:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/b57b880d72a08685fff66b6371841a1106941f2b.svg" style="height: 88px;" type="image/svg+xml"&gt;\[\begin{aligned}
    n!&amp;amp;=\int_{0}^{\infty}ne^{n\ln(ny) - ny}dy=n\int_{0}^{\infty}e^{n(\ln n+\ln y-y)}dy\\
    &amp;amp;=ne^{n\ln n}\int_{0}^{\infty}e^{n(\ln y-y)}dy
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;These steps make the integral amenable to applying &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Laplace's_method"&gt;Laplace’s
method&lt;/a&gt;, which allows
us to approximate definite integrals of the form:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/3616ce703d0d134c344d8c901ba41c86c6d4ca38.svg" style="height: 45px;" type="image/svg+xml"&gt;\[\int_{a}^{b}e^{nf(x)}dx\]&lt;/object&gt;
&lt;p&gt;Where &lt;img alt="f(x)" class="valign-m4 latex-math" src="https://eli.thegreenplace.net/images/math/3e03f4706048fbc6c5a252a85d066adf107fcc1f.png" style="height: 17px;" /&gt; is a twice-differentiable function and &lt;img alt="n" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/d1854cae891ec7b29161ccaf79a24b00c274bdaa.png" style="height: 7px;" /&gt; some
large number. By Laplace’s method, such integrals can be approximated
by:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/52bebd1bf39c848a8674b04dc7b5f9ee9725df27.svg" style="height: 54px;" type="image/svg+xml"&gt;\[\int_{a}^{b}e^{nf(x)}dx\approx\sqrt{\frac{2\pi}{n|f&amp;#x27;&amp;#x27;(x_0)|}}e^{n f(x_0)}\]&lt;/object&gt;
&lt;p&gt;Where &lt;img alt="x_0" class="valign-m3 latex-math" src="https://eli.thegreenplace.net/images/math/efbda784ad565c1c5201fdc948a570d0426bc6e6.png" style="height: 11px;" /&gt; is the global maximum of &lt;img alt="f(x)" class="valign-m4 latex-math" src="https://eli.thegreenplace.net/images/math/3e03f4706048fbc6c5a252a85d066adf107fcc1f.png" style="height: 17px;" /&gt;.&lt;/p&gt;
&lt;p&gt;Let’s see how to apply this method &lt;a class="footnote-reference" href="#footnote-3" id="footnote-reference-3"&gt;[3]&lt;/a&gt; to the latest equation we have
for &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/be86ded6f79cc18b8f5e9d7fcfc9a8c31712f5af.svg" style="height: 12px;" type="image/svg+xml"&gt;n!&lt;/object&gt; (renaming the dummy integration variable back to
&lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/11f6ad8ec52a2984abaafd7c3b516503785c2072.svg" style="height: 8px;" type="image/svg+xml"&gt;x&lt;/object&gt;):&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/253c3d3ab913e33071b5e82314a1020cd055f773.svg" style="height: 42px;" type="image/svg+xml"&gt;\[n!=ne^{n\ln n}\int_{0}^{\infty}e^{n(\ln x-x)}dx\]&lt;/object&gt;
&lt;p&gt;In our case, &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/04dc92cac4abb82f45427170ea9a147571d70700.svg" style="height: 18px;" type="image/svg+xml"&gt;f(x)=\ln x - x&lt;/object&gt;. It’s easy to show that this
function is twice differentiable and has a global maximum at
&lt;img alt="x_0=1" class="valign-m3 latex-math" src="https://eli.thegreenplace.net/images/math/0c1d7f319728a07a57d000f2379b5215e4130147.png" style="height: 15px;" /&gt;. Moreover:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/9032a58f00f68bf627a00dab927d939f9d38b851.svg" style="height: 43px;" type="image/svg+xml"&gt;\[\begin{aligned}
    f(x_0)&amp;amp;=-1\\
    f&amp;#x27;&amp;#x27;(x_0)&amp;amp;=-1\\
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;Substituting these into the proper places in Laplace’s approximation, we
get:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/2137237280a6068d803f0a0489ab8d5c2ff7174d.svg" style="height: 111px;" type="image/svg+xml"&gt;\[\begin{aligned}
    n! &amp;amp;\approx ne^{n\ln n}\sqrt{\frac{2\pi}{n}}e^{-n}\\
    &amp;amp;\approx \sqrt{2\pi n}\cdot e^{n(\ln n - 1)}\\
    &amp;amp;\approx \sqrt{2\pi n}\cdot \left(\frac{n}{e}\right)^n\quad\blacksquare
\end{aligned}\]&lt;/object&gt;
&lt;/div&gt;
&lt;div class="section" id="number-of-digits-from-stirlings-approximation"&gt;
&lt;h2&gt;Number of digits from Stirling’s approximation&lt;/h2&gt;
&lt;p&gt;We can calculate the number of digits in &lt;object class="valign-0 latex-math" data="https://eli.thegreenplace.net/images/math/be86ded6f79cc18b8f5e9d7fcfc9a8c31712f5af.svg" style="height: 12px;" type="image/svg+xml"&gt;n!&lt;/object&gt; by taking the
base-10 logarithm of Stirling’s formula:&lt;/p&gt;
&lt;object class="align-center" data="https://eli.thegreenplace.net/images/math/97423a10d2cd9a401a6126b4cbd3171bb38cee61.svg" style="height: 111px;" type="image/svg+xml"&gt;\[\begin{aligned}
\text{number of digits in n!}&amp;amp;\approx \log_{10} \left(\sqrt{2\pi n}\cdot
 \left(\frac{n}{e}\right)^n\right)\\
&amp;amp;\approx \log_{10}\left(\sqrt{2\pi n}\right)+ \log_{10}\left(\frac{n}{e}\right)^n\\
&amp;amp;\approx \log_{10}\left(\sqrt{2\pi n}\right)+ n\cdot \log_{10}\left(\frac{n}{e}\right)
\end{aligned}\]&lt;/object&gt;
&lt;p&gt;Note that the first term is not multiplied by &lt;img alt="n" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/d1854cae891ec7b29161ccaf79a24b00c274bdaa.png" style="height: 7px;" /&gt; itself;
therefore, as &lt;img alt="n" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/d1854cae891ec7b29161ccaf79a24b00c274bdaa.png" style="height: 7px;" /&gt; grows, it will become less and less noticeable.
That said, it still adds a couple of digits - so you should take it into
account if you want a more accurate approximation &lt;a class="footnote-reference" href="#footnote-4" id="footnote-reference-4"&gt;[4]&lt;/a&gt;&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-1" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Mental tricks for calculating &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/e94a447fe28f08ae87dc57434036ab7f4bb1a125.svg" style="height: 17px;" type="image/svg+xml"&gt;\log_{10}&lt;/object&gt; is a different topic,
but it really helps to remember that &lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/ea98121d7d3c34ec2b12ca3e79aa25d5a4b986f7.svg" style="height: 17px;" type="image/svg+xml"&gt;\log_{10}2=0.3&lt;/object&gt;,
&lt;object class="valign-m4 latex-math" data="https://eli.thegreenplace.net/images/math/35ef3eaf3f31f1f685a336494a1005e9e1af0922.svg" style="height: 17px;" type="image/svg+xml"&gt;\log_{10}3=0.5&lt;/object&gt;, and from here using the various logarithm
laws to estimate multiples.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-2" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;As a matter of fact, the Gamma function is defined for complex
numbers, but for our purpose talking about the reals is sufficient.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-3" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;As much as I’d like to dive into &lt;em&gt;why&lt;/em&gt; this approximation works, the
rabbit hole in this post is already deep enough!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-4" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-4"&gt;[4]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;It adds up to 2 extra digits as long as &lt;img alt="n" class="valign-0 latex-math" src="https://eli.thegreenplace.net/images/math/d1854cae891ec7b29161ccaf79a24b00c274bdaa.png" style="height: 7px;" /&gt; is less than 1600
or so, and may add more than 2 after that, though no more than 3
until n is 160000. It’s not clear why anyone would like to estimate
the number of digits of 1600! (about 4450, in case you were
wondering), let alone 160000!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</content><category term="misc"></category><category term="Math"></category></entry></feed>