<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>John D. Cook</title>
	<atom:link href="http://www.johndcook.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.johndcook.com/blog</link>
	<description>Applied Mathematics Consulting</description>
	<lastBuildDate>Mon, 24 Aug 2026 14:15:29 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.johndcook.com/wp-content/uploads/2020/01/cropped-favicon_512-32x32.png</url>
	<title>John D. Cook</title>
	<link>https://www.johndcook.com/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Three-term recurrences</title>
		<link>https://www.johndcook.com/blog/2026/08/24/three-term-recurrences/</link>
					<comments>https://www.johndcook.com/blog/2026/08/24/three-term-recurrences/#respond</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Mon, 24 Aug 2026 14:14:55 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247726</guid>

					<description><![CDATA[<p>There many examples of families of functions where each function can be computed as a linear combination of the two previous terms where a and b are functions of x but not on n. This is called a three-term recurrence formula. It&#8217;s amazing how often you can run into three-term recurrence formulas. There are theorems that give conditions [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/24/three-term-recurrences/">Three-term recurrences</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>There many examples of families of functions where each function can be computed as a linear combination of the two previous terms</p>
<p><img decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence.svg" alt="f_{n+1}(x) = a(x) f_n(x) + b(x) f_{n-1}(x)" width="276" height="18" /></p>
<p>where <em>a</em> and <em>b</em> are functions of <em>x</em> but not on <em>n</em>. This is called a three-term recurrence formula.</p>
<p>It&#8217;s amazing how often you can run into three-term recurrence formulas. There are theorems that give conditions for such recurrences to hold, but I haven&#8217;t reached the bottom of that rabbit hole [1].</p>
<p>For this post I just want to give examples.</p>
<p><strong>Bessel functions</strong> of the first and second kind:</p>
<p><img decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence_bessel.svg" alt="\begin{align*} J_{\nu+1}(x) &amp;= \frac{2\nu}{x}\,J_\nu(x) - J_{\nu-1}(x) \\ Y_{\nu+1}(x) &amp;= \frac{2\nu}{x}\,Y_\nu(x) - Y_{\nu-1}(x) \end{align*}" width="237" height="88" /></p>
<p><strong>Modified Bessel functions</strong> of the first and second kind:</p>
<p><img decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence_modified_bessel.svg" alt="\begin{align*} I_{\nu+1}(x) &amp;= I_{\nu-1}(x) - \frac{2\nu}{x}\,I_\nu(x) \\ K_{\nu+1}(x) &amp;= K_{\nu-1}(x) + \frac{2\nu}{x}\,K_\nu(x) \end{align*}" width="245" height="88" /></p>
<p><strong>Chebyshev polynomials</strong> of the first and second kind:</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence_chebyshev.svg" alt="\begin{align*} T_{n+1}(x) &amp;= 2x\,T_n(x) - T_{n-1}(x) \\ U_{n+1}(x) &amp;= 2x\,U_n(x) - U_{n-1}(x) \end{align*}" width="244" height="47" /></p>
<p><strong>Hermite polynomials</strong> (physicists&#8217; convention):</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence_hermite.svg" alt="H_{n+1}(x) = 2x\,H_n(x) - 2n\,H_{n-1}(x)" width="271" height="18" /></p>
<p><strong>Legendre polynomials</strong>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence_legendre.svg" alt="P_{n+1}(x) = \frac{2n+1}{n+1}\,x\,P_n(x) - \frac{n}{n+1}\,P_{n-1}(x)" width="335" height="40" /></p>
<p>[1] See Bochner&#8217;s theorem for orthogonal polynomials, the Nikiforov–Uvarov method, and Infeld-Hull factorization.</p>The post <a href="https://www.johndcook.com/blog/2026/08/24/three-term-recurrences/">Three-term recurrences</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/24/three-term-recurrences/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The von Mises-Fisher distribution</title>
		<link>https://www.johndcook.com/blog/2026/08/24/von-mises-fisher/</link>
					<comments>https://www.johndcook.com/blog/2026/08/24/von-mises-fisher/#respond</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Mon, 24 Aug 2026 14:14:25 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Probability]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247719</guid>

					<description><![CDATA[<p>Probability density function must integrate to 1, and so if you know a density function up to a constant, the constant is determined. When you&#8217;re looking at a probability density f(x) for the first time, it helps to ignore the normalizing constant. Concentrate on the part of the function involving x and know that the normalizing [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/24/von-mises-fisher/">The von Mises-Fisher distribution</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Probability density function must integrate to 1, and so if you know a density function up to a constant, the constant is determined.</p>
<p>When you&#8217;re looking at a probability density <em>f</em>(<em>x</em>) for the first time, it helps to ignore the normalizing constant. Concentrate on the part of the function involving <em>x</em> and know that the normalizing constant is whatever it has to be. For example, about half of the ink that it takes to write down a beta or chi-squared density is devoted to the normalization constant; the rest of the expression is easier to understand.</p>
<p>This post will do the opposite of the advice above and focus on normalization constants because this ties into the <a href="https://www.johndcook.com/blog/2026/08/23/modified-bessel-function/">previous post</a> on modified Bessel functions.</p>
<p>The <strong>von Mises</strong> probability distribution on a circle has two parameters, μ and κ, and its density function is</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/vonmises.svg" alt="f(x \mid \mu, \kappa) = \frac{\exp(\kappa \cos(x - \mu))}{2\pi I_0(\kappa)}" width="250" height="45" /></p>
<p>The normalizing constant is 2π <em>I</em><sub>0</sub>(κ). The factor of 2π is unsurprising for anything defined on a circle. The more interesting part is <em>I</em><sub>0</sub>, the modified Bessel function of order 0.</p>
<p>The <strong>von Mises-Fisher</strong> distribution is the generalization of the von Mises distribution to a sphere in <em>p</em> dimensions. The density function is</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/vonmises_fisher.svg" alt="f(\mathbf{x} \mid \boldsymbol{\mu}, \kappa) = C_{p}(\kappa) \exp \left( {\kappa \boldsymbol{\mu}^\mathsf{T} \mathbf{x} } \right)" width="247" height="36" /></p>
<p>where the normalization constant <em>C</em><sub><em>p</em></sub>(κ) is</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/vonmises_fisher_norm.svg" alt="C_{p}(\kappa)=\frac {\kappa^{p/2-1}} {(2\pi)^{p/2}I_{p/2-1}(\kappa)}" width="206" height="52" /></p>
<p>where <em>I</em><sub><em>p</em>/2 − 1</sub> is the modified Bessel function of order <em>p</em>/2 − 1. The values of <strong>x</strong> and <strong>μ</strong> are in bold face because they are now vectors, points on the unit sphere.</p>
<p>When <em>p</em> = 2, we have the &#8220;sphere&#8221; in two dimensions, i.e. the circle, and the von Mises-Fisher distribution reduces to the von Mises distribution. But where did the cosine go? The inner product of <strong>x</strong> and <strong>μ</strong> is the cosine of the angle between the two vectors.</p>
<p>When <em>p</em> = 3, obviously an important special case, the von Mises-Fisher distribution is known as the <strong>Fisher</strong> distribution. In that case the normalizing constant <em>C</em><sub>3</sub>(κ) can be written without using modified Bessel functions because when ν = ½ + <em>n</em> for an integer <em>n</em>, <em>I</em><sub>ν</sub>(<em>x</em>) is an elementary function.</p>The post <a href="https://www.johndcook.com/blog/2026/08/24/von-mises-fisher/">The von Mises-Fisher distribution</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/24/von-mises-fisher/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>What exactly is modified about a modified Bessel function?</title>
		<link>https://www.johndcook.com/blog/2026/08/23/modified-bessel-function/</link>
					<comments>https://www.johndcook.com/blog/2026/08/23/modified-bessel-function/#respond</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sun, 23 Aug 2026 18:40:57 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Differential equations]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247707</guid>

					<description><![CDATA[<p>Special functions often have arcane names that not very helpful without some context. The previous post goes into some reasons for this. This post will expand on a point at the end of the post about &#8220;modified&#8221; functions. Things are given their names for reasons. Discovering those reasons may help you understand their motivation and [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/23/modified-bessel-function/">What exactly is modified about a modified Bessel function?</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Special functions often have arcane names that not very helpful without some context. The <a href="https://www.johndcook.com/blog/2026/08/23/arcane-terminology/">previous post</a> goes into some reasons for this. This post will expand on a point at the end of the post about &#8220;modified&#8221; functions.</p>
<p>Things are given their names for reasons. Discovering those reasons may help you understand their motivation and use.</p>
<h2>Pure math perspective</h2>
<p>For each integer <em>n</em>, the modified Bessel function <em>I<sub>n</sub></em> is essentially the Bessel function <em>J<sub>n</sub></em> evaluated along the imaginary axis. Specifically,</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/modified_bessel2.svg" alt="I_n(x) = i^{-n} J_n(ix)" width="135" height="18" /></p>
<p>From a certain shallow perspective, that&#8217;s the end of the story: modified Bessel functions are modified in the sense that the argument is multiplied by <em>i</em>. And there&#8217;s a fiddly constant term up front for no apparent reason.</p>
<p>But of course that&#8217;s not the end of the story or else this wouldn&#8217;t be worth an entire post.</p>
<p>The equation above is analogous to the relationships between circular and hyperbolic functions</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/modified_bessel3.svg" alt="\begin{align*} \sin(ix) &amp;= i \sinh(x) \\ \cos(ix) &amp;= \phantom{i} \cosh(x) \\ \tan(ix) &amp;= \phantom{i} \tanh(x) \end{align*}" width="154" height="76" /></p>
<p>These relationships are interesting because the circular and hyperbolic functions are independently meaningful. If you view these equations merely as definitions you lose their significance. Circular and hyperbolic functions were widely used before Euler discovered the connection between them.</p>
<p>Similarly, there&#8217;s a reason the modified Bessel functions were given a name their own. If you were led to Bessel functions and modified Bessel functions separately by different applications, you would regard the equation</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/modified_bessel2.svg" alt="I_n(x) = i^{-n} J_n(ix)" width="135" height="18" /></p>
<p>as a <strong>discovery</strong> rather than just a definition. The following section explains why someone would be interested in modified Bessel functions.</p>
<p>Before we move on, I&#8217;d like to explain the reason for the term <em>i</em><sup>−<em>n</em></sup> term. In general</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/modified_bessel4.svg" alt="I_\nu(x) = \exp(\nu\pi i/2) J_n(ix)" width="202" height="18" /></p>
<p>for all real ν. The reason for the exp(νπ<em>i</em>/2) term is that it makes <em>I</em><sub>ν</sub>(<em>x</em>) real for all real <em>x</em>.</p>
<h2>Applied math perspective</h2>
<p>Bessel functions often arise from solving problems with <strong>radial symmetry</strong>. Solving the <strong>wave equation</strong> in cylindrical coordinates using separation of variables leads to Bessel&#8217;s differential equation</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/bessel_equation.svg" alt="x^2 y'' + x y' + (x^2 - \nu^2) y = 0" width="212" height="20" /></p>
<p>and its solutions <em>J<sub>n</sub></em> and <em>Y<sub>n</sub></em>, Bessel functions of the first and second kind.</p>
<p>Solving the <strong>heat equation</strong> in cylindrical coordinates with separation of variables leads to the <em>modified</em> Bessel equation</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/modified_bessel5.svg" alt="x^2 y^{\prime \prime} + x y^{\prime} - (x^2 + \nu^2) y = 0" width="225" height="22" /></p>
<p>and its solutions <em>I<sub>n</sub></em> and <em>K<sub>n</sub></em>, the <em>modified</em> Bessel functions of the first and second kind.</p>
<p>This is the reason behind the complex analysis perspective above: the change of variables sending <em>x</em> to <em>ix</em> changes the sign of the <em>x</em>² term in Bessel&#8217;s equation.</p>
<p>Bessel functions describe radially symmetric <strong>oscillations</strong>, such as the vibrations of a drum head. Modified Bessel functions describe radially symmetric <strong>exponential</strong> growth or decay [1], such as in the heat in a cylinder.</p>
<h2>Other modified functions</h2>
<p><strong>Struve functions</strong> are closely related to Bessel functions. The (modified) Struve functions also satisfy Bessel&#8217;s (modified) differential equation, but with a non-zero right hand side. The modified Struve functions are proportional to the unmodified Struve functions evaluated along the imaginary axis, with a proportionality constant that makes the modified Struve functions real for real arguments.</p>
<p>There&#8217;s a similar relationship between the <strong>Mathieu functions</strong> and modified Mathieu functions. The general pattern is that &#8220;modified&#8221; in the context of special functions means &#8220;evaluated at <em>ix</em> and multiplied by a constant to make the function real for real arguments.&#8221;</p>
<p>&nbsp;</p>
<p>[1] The functions <em>I<sub>n</sub></em> grow exponentially and the functions <em>K<sub>n</sub></em> decay exponentially. For this reason, <a href="https://www.johndcook.com/blog/2017/02/26/function-on-cover-of-abramowitz-stegun/">A&amp;S</a> didn&#8217;t tabulate <em>I<sub>n</sub></em> and <em>K<sub>n</sub></em> per se. Instead it tabulated <em>e</em><sup>−<em>x</em></sup><em>I<sub>n</sub></em> and <em>e</em><sup><em>x</em></sup><em>K<sub>n</sub></em> because these functions varied less over their range.</p>The post <a href="https://www.johndcook.com/blog/2026/08/23/modified-bessel-function/">What exactly is modified about a modified Bessel function?</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/23/modified-bessel-function/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Why special function terminology is arcane</title>
		<link>https://www.johndcook.com/blog/2026/08/23/arcane-terminology/</link>
					<comments>https://www.johndcook.com/blog/2026/08/23/arcane-terminology/#respond</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sun, 23 Aug 2026 17:56:03 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247705</guid>

					<description><![CDATA[<p>Special functions are special because they&#8217;re useful. They can also be shrouded in arcane terminology. These two facts are related. The more widely useful a function is, the more likely it is that the function will be discovered independently multiple times. Independent discoveries lead to varying definitions and notations. For example, there are two widely [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/23/arcane-terminology/">Why special function terminology is arcane</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Special functions are special because they&#8217;re useful. They can also be shrouded in arcane terminology. These two facts are related.</p>
<p>The more widely useful a function is, the more likely it is that the function will be discovered independently multiple times. Independent discoveries lead to varying definitions and notations. For example, there are two widely used definitions of Hermite polynomials, one used in <a href="https://www.johndcook.com/blog/2017/12/20/hermite-polynomials-expected-values-and-integration/">probability</a> and another used in physics, that only differ by a scaling factor. This also explains why there are so many variations on the definitions of the <a href="https://www.johndcook.com/blog/2022/03/20/reverse-engineering-fourier-conventions/">Fourier transform</a> and <a href="https://www.johndcook.com/blog/2023/08/12/spherical-coordinate-rosetta-stone/">spherical coordinates</a>.</p>
<p>Special functions were discovered and applied before they were studied systematically. As with most mathematics, practice preceded theory. In hindsight, some names and conventions were less than ideal, at least from the perspective of someone seeking to organize a theory.</p>
<p>Functions can have arcane names for several reasons, one being that their usefulness became apparent long ago. If you&#8217;re instinct is that things with strange names are no longer important, you&#8217;re instinct might be backward. The strange name may be an indication that something is so important that its usefulness became apparent long ago.</p>
<p>Sometimes special functions have bland, uninformative names because the names stuck before anybody could think of something better. Bob looks into an interesting family of functions [1], then later he finds another interesting family of functions. These become known as &#8220;Bob&#8217;s functions of the first kind&#8221; and &#8220;Bob&#8217;s functions of the second kind.&#8221; These names are quite understandable at the time, though in the future people will want to know what distinguishes the functions, other than the fact that Bob discovered them, and what the groupings have in common other than the order in which Bob found them.</p>
<p>I started this post intending to discuss modified Bessel functions and explain what exactly is modified about them, but my preface became its own post. &#8220;Modified&#8221; is an example of the bland terminology mentioned above. There are Bessel functions and modified Bessel functions. Without more context, the &#8220;modified&#8221; term isn&#8217;t very informative. But it does provide a clue that there&#8217;s some kind of close relationship between the modified and unmodified functions. That&#8217;ll be the topic of my next post.</p>
<p>&nbsp;</p>
<p>[1] Math education doesn&#8217;t place much emphasis on history and motivation. You may have to do some digging to find out why Bob was interested in his functions. What else was Bob known for? Maybe they&#8217;re related.</p>The post <a href="https://www.johndcook.com/blog/2026/08/23/arcane-terminology/">Why special function terminology is arcane</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/23/arcane-terminology/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The difference orbit inclination makes</title>
		<link>https://www.johndcook.com/blog/2026/08/22/inclination/</link>
					<comments>https://www.johndcook.com/blog/2026/08/22/inclination/#respond</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sun, 23 Aug 2026 00:01:10 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Orbital mechanics]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247702</guid>

					<description><![CDATA[<p>Suppose you wanted to find the distance between Earth and Mars over time. To first approximation, both planets orbit the sun in elliptic orbits in the same plane. If you wanted to be more accurate, you&#8217;d need to take into account the fact that the orbit of Mars is tilted about 1.85° relative to the [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/22/inclination/">The difference orbit inclination makes</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Suppose you wanted to find the distance between Earth and Mars over time. To first approximation, both planets orbit the sun in elliptic orbits in the same plane.</p>
<p>If you wanted to be more accurate, you&#8217;d need to take into account the fact that the orbit of Mars is tilted about 1.85° relative to the Earth&#8217;s orbit. How much difference does that make?</p>
<p>To simplify things, let&#8217;s assume the Earth orbits the sun in a circle of radius 1 and Mars orbits the sun in a circle of radius 1.5. The distance between Earth and Mars over time would be basically sinusoidal.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/mars_distance0.png" width="480" height="360" /></p>
<p>How much does inclination contribute to this distance? In other words, what is the difference between the distance accounting for the inclination of Mars&#8217; orbit and the distance if we assume the two orbits are in the same plane?</p>
<p>This plot gives the answer.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/mars_distance1.png" width="480" height="360" /></p>
<p>The effect is not large, about three orders of magnitude smaller than the main effect, but it&#8217;s interesting how erratic it is.</p>
<p>The plots were made with the following code.</p>
<pre>from numpy import *

R = 1.5
T = R**1.5 # Kepler's third law

def f(t, theta):
    return sqrt(
        (cos(t) - R*cos(t/T)*cos(theta))**2 +
        (sin(t) - R*sin(t/T))**2 +
        (R*sin(theta)*cos(t/T))**2
    )
</pre>
<p>The first plot graphs <em>f</em>(<em>t</em>, θ) and the second graphs <em>f</em>(<em>t</em>, θ) − <em>f</em>(<em>t</em>, 0).</p>The post <a href="https://www.johndcook.com/blog/2026/08/22/inclination/">The difference orbit inclination makes</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/22/inclination/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Coming soon</title>
		<link>https://www.johndcook.com/blog/2026/08/22/coming-soon/</link>
					<comments>https://www.johndcook.com/blog/2026/08/22/coming-soon/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sat, 22 Aug 2026 15:34:11 +0000</pubDate>
				<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Probability and Statistics]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247699</guid>

					<description><![CDATA[<p>There&#8217;s a pizza shop near my home with a sign out front that says &#8220;Coming Soon.&#8221; When I drove by it this morning I thought about how you would model the time until an event happens that is &#8220;coming soon.&#8221; Suppose I look at the sign one day and guess how many days until the [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/22/coming-soon/">Coming soon</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>There&#8217;s a pizza shop near my home with a sign out front that says &#8220;Coming Soon.&#8221; When I drove by it this morning I thought about how you would model the time until an event happens that is &#8220;coming soon.&#8221;</p>
<p>Suppose I look at the sign one day and guess how many days until the pizza shop will open. When I drive by a week later and guess again, should my guess be smaller? You might argue that the shop will open some day, fixed in time but unknown to me, and so every day I&#8217;m one day closer to the eventual opening.</p>
<p>You might model the pizza shop opening like radioactive decay and say that the estimated number of days until it opens is always the same until the day it actually opens.</p>
<p>Now I think this shop has been &#8220;coming soon&#8221; for over a year. So instead of decreasing, every day I increase my estimate of the time until the shop opens. Something has gone wrong that the owners didn&#8217;t expect when they put up the sign.</p>
<p>Maybe the reasonable thing would be for estimated days until opening to decrease over time, but only up to a point. After some point, the longer a business has been &#8220;coming soon&#8221; the less like that it is coming soon, or coming at all.</p>
<p>This brings up an interesting point about modeling. There are two probability distributions at work: the probability that the shop will eventually open, and the time until opening assuming it eventually opens.</p>
<p>When the sign first goes up saying the business is coming soon, there&#8217;s some change that it is in fact not coming. Maybe you&#8217;re optimistic and think this probability is small, but it would seem unreasonable to think the probability is zero. That means the <em>expected</em> number of days until opening is always infinite. If there&#8217;s a probability ε that the shop never opens, the expected time to opening is</p>
<p style="padding-left: 40px;">ε × ∞ + (1 − ε) × something = ∞.</p>The post <a href="https://www.johndcook.com/blog/2026/08/22/coming-soon/">Coming soon</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/22/coming-soon/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>How would you know whether an ancient culture had zero?</title>
		<link>https://www.johndcook.com/blog/2026/08/21/ancient-number-system/</link>
					<comments>https://www.johndcook.com/blog/2026/08/21/ancient-number-system/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Fri, 21 Aug 2026 13:14:28 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Number systems]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247692</guid>

					<description><![CDATA[<p>A few weeks ago I wrote about the number system used in labeling spreadsheet columns. Labels run from A through Z, then AA through AZ, etc. This looks a lot like base 26, but it&#8217;s not quite the same. It has no analog of zero. If Z were like zero, Y would be followed by [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/21/ancient-number-system/">How would you know whether an ancient culture had zero?</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p><a href="https://www.johndcook.com/blog/2026/07/25/excel-column-numbering/">A few weeks ago</a> I wrote about the number system used in labeling spreadsheet columns. Labels run from A through Z, then AA through AZ, etc. This looks a lot like base 26, but it&#8217;s not quite the same. It has no analog of zero. If Z were like zero, Y would be followed by AZ. The Excel labeling system is not base 26, but what&#8217;s called bijective base 26.</p>
<p>If you found fragments of writing from an ancient culture and inferred that five symbols were used as digits, how could you distinguish base 5 from bijective base 5? Suppose you believe these five symbols were digits</p>
<p style="padding-left: 40px;">★ <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2602.png" alt="☂" class="wp-smiley" style="height: 1em; max-height: 1em;" />︎ <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2618.png" alt="☘" class="wp-smiley" style="height: 1em; max-height: 1em;" />︎ ☗ <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2622.png" alt="☢" class="wp-smiley" style="height: 1em; max-height: 1em;" />︎</p>
<p>but you don&#8217;t know in what order. You just see sequences like <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2602.png" alt="☂" class="wp-smiley" style="height: 1em; max-height: 1em;" />&#xfe0e;<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2618.png" alt="☘" class="wp-smiley" style="height: 1em; max-height: 1em;" />&#xfe0e;<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2622.png" alt="☢" class="wp-smiley" style="height: 1em; max-height: 1em;" />&#xfe0e; and ★★<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2602.png" alt="☂" class="wp-smiley" style="height: 1em; max-height: 1em;" />&#xfe0e; and believe they&#8217;re numbers.</p>
<p>If you noticed that numbers often contain <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2618.png" alt="☘" class="wp-smiley" style="height: 1em; max-height: 1em;" />&#xfe0e;, but <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2618.png" alt="☘" class="wp-smiley" style="height: 1em; max-height: 1em;" />&#xfe0e; never appears at the beginning of a number, you might infer that <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2618.png" alt="☘" class="wp-smiley" style="height: 1em; max-height: 1em;" />&#xfe0e; is a zero. But this would take a fairly large sample. If you found only 20 numbers, for example, you could hardly conclude <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2618.png" alt="☘" class="wp-smiley" style="height: 1em; max-height: 1em;" />&#xfe0e; never appears at the beginning of a number just because it doesn&#8217;t come at the beginning of any number you&#8217;ve seen.</p>
<p>Now suppose you&#8217;ve found writing with more number symbols. Say you&#8217;ve found 17 numeric symbols. You might infer that the writing used a base 20 system, because it would be hard to imagine a human culture using base 17. Now imagine you find more fragments and confirmed that indeed there are 20 numeric symbols. Approached as a purely statistical problem, you&#8217;d need a very large sample to infer what the digits correspond to and whether they use a base 20 or bijective base 20 system (or some other system).</p>
<p>You&#8217;re best hope is to find numbers in some context where you know what number is being represented. If you knew somehow that some symbol corresponds to 20, then you&#8217;d know they didn&#8217;t use base 20 because base <em>b</em> doesn&#8217;t have a single symbol for <em>b</em>.</p>
<p>If you had a huge collection of numbers but no context, which is highly unlikely, you could use <a href="https://www.johndcook.com/blog/benfords-law/">Benford&#8217;s law</a> to infer the meaning of the number symbols: the most common leading digit is probably 1, the next most common is probably 2, etc. This is interesting to think about, but it seems much more realistic that a number system would be decoded by finding context, such as a list of consecutive numbers or numbers with known meaning.</p>
<p>&nbsp;</p>The post <a href="https://www.johndcook.com/blog/2026/08/21/ancient-number-system/">How would you know whether an ancient culture had zero?</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/21/ancient-number-system/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>AI-generated ASCII diagrams</title>
		<link>https://www.johndcook.com/blog/2026/08/20/ai-generated-ascii-diagrams/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Thu, 20 Aug 2026 13:48:43 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247682</guid>

					<description><![CDATA[<p>I like AI-generated ASCII diagrams. Because nobody would ask AI to generate ASCII diagrams, and so, it&#8217;s congruous. I like incongruity [1]. Aside from the incongruity of using a gazillion-parameter neural network to make 1970&#8217;s style ASCII art, ASCII diagrams have some uses. They&#8217;re absolutely tiny compared to image files. But more importantly they can [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/20/ai-generated-ascii-diagrams/">AI-generated ASCII diagrams</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>I like AI-generated ASCII diagrams. Because nobody would ask AI to generate ASCII diagrams, and so, it&#8217;s congruous. I like incongruity [1].</p>
<p>Aside from the incongruity of using a gazillion-parameter neural network to make 1970&#8217;s style ASCII art, ASCII diagrams have some uses. They&#8217;re absolutely tiny compared to image files. But more importantly they can be inserted into plain text files, such as source code or markdown. A diagram embedded directly into a source file cannot become separated from the code.</p>
<p>ASCII diagrams are tedious to create, though there are <a href="https://www.johndcook.com/blog/2016/06/15/ascii-art-diagrams-in-emacs-org-mode/">tools</a> to mitigate the tedium. But if an AI can generate the diagram, the tedium goes away.</p>
<p>I was curious how well Claude could create ASCII diagrams, so I tried a few examples. I hope these render well in whatever format you&#8217;re reading this post. They look fine for me previewing the post in a browser. I expect they might not turn out so well in an RSS reader.</p>
<p>I asked it to reproduce the graphs from my recently post on the <a href="https://www.johndcook.com/blog/2026/08/18/the-imbalance-theorem/">graph imbalance theorem</a> and the first diagram turned out nicely.</p>
<pre style="font-size: 12px; line-height: 1.2; overflow-x: auto;">
                 +-------+                                +-------+
                 |   A   |--------------------------------|   B   |
                 +-------+                                +-------+
                     |                                        |
                     |                                        |
   ------------------|------------------             ---------|---------
   |        |        |        |        |             |        |        |
   |        |        |        |        |             |        |        |
+-----+  +-----+  +-----+  +-----+  +-----+       +-----+  +-----+  +-----+
| a0  |  | a1  |  | a2  |  | a3  |  | a4  |       | b0  |  | b1  |  | b2  |
+-----+  +-----+  +-----+  +-----+  +-----+       +-----+  +-----+  +-----+
</pre>
<p>The second network is more complicated and so the corresponding ASCII diagram is hard to read.</p>
<pre style="font-size: 12px; line-height: 1.2; overflow-x: auto;">
   +----------------------------------------------------------------+
   |                                                                |
   |+-----------------------------------------------+               |
   ||                                               |               |
   ||+-------------------------------+              |               |
  +-------+       +-------+       +-------+       +-------+       +-------+
  |  R1   |-------|  R2   |-------|  R3   |-------|  R4   |-------|  R5   |
  +-------+       +-------+       +-------+       +-------+       +-------+
      |             | | |          |   |           |   |           |  |  |
     ++             | | |          |   |           |   |           |  |  |
     | +---------------------------+   |           |   |           |  |  |
     | |            ++| |              |           |   |           |  |  |
     | |             || +--------------+           |   |           |  |  |
     | |             || |  +---------------------------------------+  |  |
     | |             |+-|--|-------------+         |   |              |  |
     | |             |  |  |             |  +------+   |              |  |
     | |             |  |  |             |  |  +----------------------+  |
     | |             |  +--|-------------|--|--|-------------+           |
     | |             |  |  |             |  |  |       +-----|--+        |
     | |             |  |  |             |  |  |             |  |  +-----+
     | |             |  |  |             |  |  |             |  |  |
  +-------+         +-------+           +-------+           +-------+
  |  G1   |         |  B1   |           |  B2   |           |  B3   |
  +-------+         +-------+           +-------+           +-------+
</pre>
<p>For a third example, here is a fairly complicated diagram that nevertheless lends itself to a readable ASCII diagram. It&#8217;s a <a href="https://www.johndcook.com/blog/2020/04/04/feistel-networks/">Feistel network</a> diagram for DES encryption.</p>
<pre style="font-size: 12px; line-height: 1.2; overflow-x: auto;">
   +-------------+                    +-------------+
   |   L(i-1)    |                    |   R(i-1)    |--------
   +-------------+                    +-------------+       |
          |                                  |              |
          |                                  |              |
          |                      +-----------------------+  |
          |                      |   E (expand 32->48)   |  |
          |                      +-----------------------+  |
          |                                  |              |
          |                      +-----------------------+  |
          |                      |     XOR with K(i)     |  |
          |                      +-----------------------+  |
          |                                  |              |
          |                      +-----------------------+  |
          |                      |    S-boxes S1..S8     |  |
          |                      +-----------------------+  |
          |                                  |              |
          |                      +-----------------------+  |
          |                      |    P (permutation)    |  |
          |                      +-----------------------+  |
          |                                  |              |
          |                                  |              |
          |            +-------+             |              |
          +------------|  XOR  |-------------+              |
                       +-------+                            |
                           |                                |
          +----------------|--------------------------------+
          |                +------------------+
          |                                   |
   +-------------+                    +-------------+
   |    L(i)     |                    |    R(i)     |
   +-------------+                    +-------------+
</pre>
<h2>Related posts</h2>
<ul>
<li class='link'><a href='https://www.johndcook.com/blog/2020/07/25/worst-tool-for-the-job/'>The worst tool for the job</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2023/12/11/ascii-armor/'>ASCII armor</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2022/05/28/how-to-memorize-the-ascii-table/'>Memorizing the ASCII table</a></li>
</ul>
<p>[1] See Christian Wolff&#8217;s discussion of dogs playing poker in The Accountant (2016).</p>The post <a href="https://www.johndcook.com/blog/2026/08/20/ai-generated-ascii-diagrams/">AI-generated ASCII diagrams</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Big little hexagon</title>
		<link>https://www.johndcook.com/blog/2026/08/18/big-little-hexagon/</link>
					<comments>https://www.johndcook.com/blog/2026/08/18/big-little-hexagon/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 19 Aug 2026 00:22:36 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Geometry]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247675</guid>

					<description><![CDATA[<p>A new paper just came out, The Maximum-Area Small Polygon Problem. The paper solves the problem of finding, for each n, the n-gon with diameter 1 and maximum area. For odd n, the solution is what you might expect: a regular n-gon. I would expect this to be the solution for even n as well, [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/18/big-little-hexagon/">Big little hexagon</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>A new paper just came out, <a href="https://arxiv.org/abs/2608.15666v1">The Maximum-Area Small Polygon Problem</a>. The paper solves the problem of finding, for each <em>n</em>, the <em>n</em>-gon with diameter 1 and maximum area.</p>
<p>For odd <em>n</em>, the solution is what you might expect: a regular <em>n</em>-gon. I would expect this to be the solution for even <em>n</em> as well, but it&#8217;s not. </p>
<p>In 1974 [1] Ron Graham found a solution for <em>n</em> = 6, a hexagon with unit diameter and area larger than a regular hexagon with unit diameter. Polygons with diameter ≤ 1 are called &#8220;small&#8221;, and he found the &#8220;largest&#8221; (i.e. maximum area) small hexagon.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/graham_hexagon.png" width="410" height="410" /></p>
<p>The vertices of Graham&#8217;s hexagon are given below.</p>
<pre>  A = (0.0000000000,  0.0000000000)
  C = (0.4023506913, -0.5000000000)
  F = (0.9390533483, -0.3437714489)
  B = (1.0000000000,  0.0000000000)
  E = (0.9390533483,  0.3437714489)
  D = (0.4023506913,  0.5000000000)
</pre>
<p>You can verify that the distance between any pair of vertices is no more than 1 and that the area of Graham&#8217;s hexagon is 0.674981.</p>
<p>The area of a regular hexagon of diameter 1 is (3/8)&radic;3 = 0.649519, and the area of Graham&#8217;s hexagon is about 3.9% larger.</p>
<p>[1] R. L. Graham. The Largest Small Hexagon. Journal of Combinatorial Theory (A) 18, 165–170 (1975). The paper was submitted February 22, 1974 and published in 1975.</p>The post <a href="https://www.johndcook.com/blog/2026/08/18/big-little-hexagon/">Big little hexagon</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/18/big-little-hexagon/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>The imbalance theorem</title>
		<link>https://www.johndcook.com/blog/2026/08/18/the-imbalance-theorem/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Tue, 18 Aug 2026 15:54:57 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Networks]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247668</guid>

					<description><![CDATA[<p>The imbalance conjecture is now a theorem. James Alexander Schreib and Yousof Yavari posted a proof last week. What does the conjecture theorem say? Start with a graph G with no edge between two nodes of the same degree. Then for every edge, calculate the absolute value of the difference of the degree of each end. [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/18/the-imbalance-theorem/">The imbalance theorem</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>The imbalance conjecture is now a theorem. James Alexander Schreib and Yousof Yavari posted a <a href="https://arxiv.org/abs/2608.09191">proof</a> last week.</p>
<p>What does the <del>conjecture</del> theorem say? Start with a graph <em>G</em> with no edge between two nodes of the same degree. Then for every edge, calculate the absolute value of the difference of the degree of each end. The imbalance theorem says there exists another graph <em>H</em> whose vertices have degrees corresponding to the differences of degrees in <em>G</em>.</p>
<p>For example, let <em>G</em> be the graph below.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/no_equal_degree_graph.png" width="533" height="400" /></p>
<p>The edges from the top red vertex <em>A</em> to each of the blue vertices around it all have degree difference 5 because <em>A</em> has degree 6 and the vertices <em>a</em><sub>0</sub> to <em>a</em><sub>4</sub> have degree 1. The edge between the two red vertices, <em>A</em> and <em>B</em>, has degree difference 2. The remaining vertices have degree difference 3.</p>
<p>So the <a href="https://www.johndcook.com/blog/2022/10/26/multisets/">multiset</a> of degree differences is</p>
<p style="padding-left: 40px;">{5, 5, 5, 5, 5, 2, 3, 3, 3}</p>
<p>The imbalance theorem says there exists a graph <em>H</em> whose nodes have these degrees. Here is an example of such an <em>H</em>.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/degree_sequence_graph.png" width="461" height="461" /></p>
<p>Note that in <em>H</em>, the 5 red nodes have degree 5, the single green node has degree 2, and the three blue nodes have degree 3.</p>
<h2>More graph posts</h2>
<ul>
<li class='link'><a href='https://www.johndcook.com/blog/2023/08/10/texas-tour/'>Traveling salesman tour of Texas</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2025/05/21/effective-graph-resistance/'>Effective graph resistence</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2017/02/21/visualizing-graph-spectra-like-chemical-spectra/'>Visualizing graph spectra</a></li>
</ul>The post <a href="https://www.johndcook.com/blog/2026/08/18/the-imbalance-theorem/">The imbalance theorem</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Mean distance to the sun</title>
		<link>https://www.johndcook.com/blog/2026/08/18/mean-distance-to-the-sun/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Tue, 18 Aug 2026 13:42:06 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Orbital mechanics]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247662</guid>

					<description><![CDATA[<p>Suppose you have a planet in an elliptical orbit around a star. The math is identical for any light object orbiting a heavy object, such as a moon or satellite orbiting a planet, but we&#8217;ll call the heavy object a star and the light object a planet. The center of the star is not quite [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/18/mean-distance-to-the-sun/">Mean distance to the sun</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Suppose you have a planet in an elliptical orbit around a star. The math is identical for any light object orbiting a heavy object, such as a moon or satellite orbiting a planet, but we&#8217;ll call the heavy object a star and the light object a planet.</p>
<p>The center of the star is not quite the center of the orbit. The planet moves along an ellipse with the star at one focus of that ellipse.</p>
<p>Let <em>a</em> be the semi-major axis of planet&#8217;s orbit, the maximum distance from the center of the ellipse to a point on the ellipse. Then the distance of a focus to the center of the ellipse is <em>ae</em> where <em>e</em> is the eccentricity of the ellipse. This defines eccentricity. The center of earth&#8217;s orbit is between three and four solar radii away from the center of the sun [1].</p>
<p>The planet is farthest from the star when it is along the major axis of the ellipse on the opposite side as the star. The distance is then <em>a</em> + <em>ae</em>, the distance to the center plus the distance from the center to the star. On the opposite side of its orbit, the planet is closest to the star. There the distance is <em>a</em> − <em>ae</em>. In summary the maximum distance to the star is</p>
<p style="padding-left: 40px;"><em>a</em>(1 + <em>e</em>)</p>
<p>and the minimum distance is</p>
<p style="padding-left: 40px;"><em>a</em>(1 − <em>e</em>).</p>
<p>If you had to guess the <em>average</em> distance between the planet and its star, <em>a</em> would be a good guess since it&#8217;s the average of the maximum and minimum distance. And that&#8217;s a good approximation, provided <em>e</em> is small. The mean distance over time is</p>
<p style="padding-left: 40px;"><em>a</em>(1 + ½<em>e</em>²).</p>
<p>See <a href="https://www.johndcook.com/mean_distance_to_sun.pdf">derivation</a>. The average distance is greater than <em>a</em> because the planet moves faster when nearest the star and slower when further from the star.</p>
<p>The relative error in approximating the mean distance by <em>a</em> is then ½<em>e</em>². When <em>e</em> is small, ½<em>e</em>² is very small. For the earth&#8217;s orbit, <em>e</em> = 0.01671, and so the approximation is off by around 0.014%.</p>
<p>The eccentricity of Pluto&#8217;s orbit is 0.2488, and so in that case the approximation is off by about 3.1%. The eccentricity of a Molniya orbit, used by some Russian satellites, is 0.74 [2]. For such satellites the error in approximating the mean distance to earth as the semimajor axis is around 27%.</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2025/02/28/max-min-orbital-speed/">Min and max orbital speed</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2026/04/03/roman-moon-greek-moon/">Roman moon, Greek moon</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2026/06/06/from-kepler-to-bessel/">From Kepler to Bessel</a></li>
</ul>
<p>[1] For earth&#8217;s orbit, <em>e</em> = 0.01671, <em>a</em> = 1.496×10<sup>11</sup> m, and the sun&#8217;s radius is <em>r</em> = 6.957×10<sup>8</sup> m. And so <em>ea</em> / <em>r</em> = 3.59.</p>
<p>[2] An object in such a highly elliptical orbit will spend a long time at the far side of its orbit, i.e. over Russia. Sort of a poor man&#8217;s geostationary orbit.</p>The post <a href="https://www.johndcook.com/blog/2026/08/18/mean-distance-to-the-sun/">Mean distance to the sun</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Proportion of 1s in a Hadamard matrix</title>
		<link>https://www.johndcook.com/blog/2026/08/16/proportion-of-1s-in-a-hadamard-matrix/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Mon, 17 Aug 2026 01:16:39 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Combinatorics]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247651</guid>

					<description><![CDATA[<p>The first post in the recent series of posts on Hadamard matrices describes a way of constructing new Hadamard matrices from two other Hadamard matrices by taking their Kronecker product. Starting with a Hadamard matrix H0 and a Hadamard matrix G, you can construct a sequence of Hadamard matrices by Hn+1 = G ⊗ Hn for  [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/16/proportion-of-1s-in-a-hadamard-matrix/">Proportion of 1s in a Hadamard matrix</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>The <a href="https://www.johndcook.com/blog/2026/08/13/constructing-hadamard-matrices/">first post</a> in the recent series of posts on Hadamard matrices describes a way of constructing new Hadamard matrices from two other Hadamard matrices by taking their <a href="https://www.johndcook.com/blog/2020/04/13/kronecker-product-hadamard-matrix/">Kronecker product</a>.</p>
<p>Starting with a Hadamard matrix <em>H</em><sub>0</sub> and a Hadamard matrix <em>G</em>, you can construct a sequence of Hadamard matrices by</p>
<p style="padding-left: 40px;"><em>H</em><sub><em>n</em>+1</sub> = <em>G</em> ⊗ <em>H</em><sub><em>n</em></sub></p>
<p>for  positive integers <em>n</em>. This is known as the generalized Sylvester method.</p>
<p>Let <em>p</em><sub><em>n</em></sub> be the proportion of 1s in <em>H</em><sub><em>n</em></sub> and let <em>q</em> be the proportion of 1s in <em>G</em>. Then you can show that the recurrence holds</p>
<p style="padding-left: 40px;"><em>p</em><sub><em>n</em>+1</sub> = <em>q</em> <em>p</em><sub><em>n</em></sub> + (1 − <em>q</em>)(1 − <em>p<sub>n</sub></em>).</p>
<p>You can solve the recurrence to show that</p>
<p style="padding-left: 40px;">lim<sub><em>n</em> → ∞</sub> <em>p</em><sub><em>n</em></sub> = ½</p>
<p>and so as the iterations proceed, the ratio of number of 1s to the number of −1s approaches 1.</p>
<p>This doesn&#8217;t say anything Hadamard matrices in general, but it does apply to all Hadamard matrices created by repeatedly applying the generalized Sylvester method.</p>
<p>If you set <em>G</em> and <em>H</em> equal to the matrix</p>
<p><img loading="lazy" decoding="async" class="aligncenter" src="https://www.johndcook.com/hadamard2.svg" alt=" \begin{bmatrix} 1 &amp; 1\\ 1 &amp; -1 \end{bmatrix}" width="64" height="48" /></p>
<p>then <em>p</em><sub>0</sub> = <em>q</em> = ¾. Then for <em>n</em> = 1, 2, 3, …, 8 the values of <em>p</em><sub><em>n</em></sub> are</p>
<p style="padding-left: 40px;">0.625<br />
0.5625<br />
0.53125<br />
0.515625<br />
0.5078125<br />
0.50390625<br />
0.501953125<br />
0.5009765625.</p>
<p>&nbsp;</p>The post <a href="https://www.johndcook.com/blog/2026/08/16/proportion-of-1s-in-a-hadamard-matrix/">Proportion of 1s in a Hadamard matrix</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Probability of correcting errors</title>
		<link>https://www.johndcook.com/blog/2026/08/15/probability-of-correcting-errors/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sat, 15 Aug 2026 16:33:56 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Coding theory]]></category>
		<category><![CDATA[Probability and Statistics]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247646</guid>

					<description><![CDATA[<p>Error correcting codes are most simply described in terms of the errors they can certainly correct. For example, the Hadamard code used for the Mariner 9 probe to Mars encoded each 6-bit pixel to a 32-bit codeword in such a way that the original pixel could be recovered if no more than 7 bits were [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/15/probability-of-correcting-errors/">Probability of correcting errors</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Error correcting codes are most simply described in terms of the errors they can certainly correct. For example, the Hadamard code used for the <a href="https://www.johndcook.com/blog/2026/08/13/mariner-hadamard/">Mariner 9</a> probe to Mars encoded each 6-bit pixel to a 32-bit codeword in such a way that the original pixel could be recovered if no more than 7 bits were corrupted in transit.</p>
<p>What is the <em>probability </em>that a pixel could be repaired if corrupted? That depends on your probability model. We will assume that the probability of each bit being flipped is <em>p</em> and that errors are independent.</p>
<p>(Are errors independent, i.e. if a bit flips, is the next bit more or less likely to flip? That would depend on context.)</p>
<p>It&#8217;s straight-forward to calculate the probability that 7 or fewer or fewer bits out of 32 flip; this is the cumulative distribution of a binomial random variable. The following Python code will return the probability of <em>k</em> or fewer successes out of <em>n</em> trials, each with probability of success <em>p</em>:</p>
<pre>    from scipy.stats import binom
    print(binom.cdf(k, n, p))</pre>
<p>For example, if there is a 10% chance that each bit will flip, there&#8217;s a 98.8% chance that 7 or fewer bits out of 32 will flip.</p>
<p>However this only gives a <strong>lower bound</strong> on the probability of correcting an error. If eight bits flip in transit, we cannot tell with certainty which codeword was sent, but there will be a couple possibilities that stand out. We&#8217;ll have to guess, but we&#8217;ve narrowed down the possibilities. With even more flipped bits, there&#8217;s always a chance of recovering the original data. Still, the lower bound captures most of the probability of recovery.</p>
<p>Now suppose you&#8217;re given a desired error recovery rate and have to determine what value of <em>p</em> it can sustain. For example, someone might say they want a 98.8% chance of recovering a pixel correctly, and you could come back and say <em>p</em> must be less than or equal to 0.1. This would be a conservative answer because as discussed above, <em>p</em> = 0.1 gives a pixel recovery probability of something more than 98.8, though it&#8217;s messy to calculate how much more.</p>
<p>You could solve for <em>p</em> by trial and error, or you could use some more sophisticated math to compute <em>p</em> directly. Given a probability <em>F</em>, you can solve for <em>p</em> such that the probability of up to <em>k</em> successes out of <em>n</em> trials using the inverse of the regularized incomplete beta function.</p>
<pre>from scipy.special import betaincinv
p = 1 - betaincinv(n - k, k + 1, F)
</pre>
<p>Calculating <em>F</em> given <em>n</em>, <em>k</em>, and <em>p</em> could be a homework exercise in an introductory probability course. Solving for <em>p</em> given <em>F</em>, <em>n</em>, and <em>k</em> either requires some numerical programming or special functions and so would be a more challenging problem.</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2019/10/18/golay-code/">Golay code used in Voyager</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2019/09/12/vin-check-sum/">Vehicle Identification Number checksum</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2023/04/18/luhn-checksum/">Credit card checksum</a></li>
</ul>The post <a href="https://www.johndcook.com/blog/2026/08/15/probability-of-correcting-errors/">Probability of correcting errors</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Compressing a Hadamard matrix</title>
		<link>https://www.johndcook.com/blog/2026/08/15/compressing-a-hadamard-matrix/</link>
					<comments>https://www.johndcook.com/blog/2026/08/15/compressing-a-hadamard-matrix/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sat, 15 Aug 2026 15:40:43 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Combinatorics]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247641</guid>

					<description><![CDATA[<p>Hadamard matrices are in the news following the recent announcement of a newly discovered Hadamard matrix. I&#8217;ve written three posts on Hadamard matrices recently, one as a sort of introduction and two on applications: the error correcting code used in the Mariner 9 probe and constructing sphere packings. A Hadamard matrix is an orthogonal matrix [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/15/compressing-a-hadamard-matrix/">Compressing a Hadamard matrix</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Hadamard matrices are in the news following the recent announcement of a newly discovered Hadamard matrix. I&#8217;ve written three posts on Hadamard matrices recently, one as a sort of <a href="https://www.johndcook.com/blog/2026/08/13/constructing-hadamard-matrices/">introduction</a> and two on applications: the error correcting code used in the <a href="https://www.johndcook.com/blog/2026/08/13/mariner-hadamard/">Mariner 9</a> probe and constructing <a href="https://www.johndcook.com/blog/2026/08/13/hadamard-sphere-packing/">sphere packings</a>.</p>
<p>A Hadamard matrix is an orthogonal matrix with all entries equal to ±1. Jacques Hadamard conjectured that there exist Hadamard matrices of order 4<em>n</em> for all positive integers <em>n</em>. It&#8217;s necessary that the order be divisible by 4, and Hadamard conjectured that this is sufficient [1].</p>
<p>How could you compactly represent a Hadamard matrix? Since the entries are all either 1 or − 1 each entry could be represented by a single bit, and <em>n</em>² bits could store an <em>n</em> × <em>n</em> Hadamard matrix. But we can do better.</p>
<h2>Methodical matrices</h2>
<p>If the matrix can be produced by an algorithm, you only need to store the name of the algorithm and the argument to the algorithm. So, for a 1024 × 1024 matrix applied by iterating Sylvester&#8217;s algorithm could be stored by saying &#8220;Apply Sylvester&#8217;s algorithm 10 times&#8221; rather than storing a megabyte of data.</p>
<p>Paley&#8217;s method can create a Hadamard matrix corresponding to every prime power. So you could determine a Paley type matrix by storing the prime and the exponent.</p>
<p>Next in complexity would be hybrid algorithms, such as start with the Paley method applied to 37<sup>6</sup> and then apply Sylvester&#8217;s method 3 times.</p>
<p>There are more methods of creating Hadamard matrices than Sylvester&#8217;s method and Paley&#8217;s method, though they&#8217;re harder to describe and parameterize.</p>
<h2>Sporadic matrices</h2>
<p>If a Hadamard matrix cannot be constructed using an algorithm, you can still store the matrix in fewer than <em>n</em>² bits. Since the rows are orthogonal, the last row of the matrix is determined by all the previous rows, up to sign. So you could store a Hadamard matrix using <em>n</em>(<em>n</em> − 1) + 1 bits.</p>
<p>Some Hadamard matrices are symmetric or skew. A symmetric matrix is determined by its diagonal and the elements above the diagonal. So a symmetric Hadamard matrix could be represented by <em>n</em>(<em>n</em> + 1)/2 bits.</p>
<p>A skew Hadamard matrix isn&#8217;t quite skew-symmetric. A matrix <em>M</em> is skew symmetric if</p>
<p style="padding-left: 40px;"><em>M</em><sup>T</sup> = −<em>M</em>.</p>
<p>This implies the diagonal elements are 0, and Hadamard matrices cannot contain 0s. A Hadamard matrix <em>H</em> is called skew if</p>
<p style="padding-left: 40px;"><em>H</em> + <em>H</em><sup>T</sup> = 2<em>I</em>.</p>
<p>This implies the diagonal elements are all 1s and the elements below the diagonal have the opposite sign of the elements above the diagonal. Since the elements on the diagonal are determined, a skew Hadamard matrix can be sorted using <em>n</em>(<em>n</em> − 1)/2 bits.</p>
<p>Incidentally, there is a conjecture that there exist skew Hadamard matrices of order 4<em>n</em> for all positive <em>n</em>.</p>
<p>&nbsp;</p>
<p>[1] There are Hadamard matrices of order 1 and 2, but larger orders must be divisible by 4.</p>The post <a href="https://www.johndcook.com/blog/2026/08/15/compressing-a-hadamard-matrix/">Compressing a Hadamard matrix</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/15/compressing-a-hadamard-matrix/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Hadamard Codes and Sphere Packing</title>
		<link>https://www.johndcook.com/blog/2026/08/13/hadamard-sphere-packing/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Fri, 14 Aug 2026 01:35:05 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Geometry]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247637</guid>

					<description><![CDATA[<p>Yesterday Levent Alpöge announced that he and his colleagues had discovered a new Hadamard matrix using Claude AI. That motivated a post I wrote this morning on how to construct Hadamard matrices. I mentioned in that post that these matrices arise in applications. This evening I gave an example, describing how NASA used a Hadamard [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/13/hadamard-sphere-packing/">Hadamard Codes and Sphere Packing</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Yesterday Levent Alpöge announced that he and his colleagues had discovered a new Hadamard matrix using Claude AI. That motivated a post I wrote <a href="https://www.johndcook.com/blog/2026/08/13/constructing-hadamard-matrices/">this morning</a> on how to construct Hadamard matrices. I mentioned in that post that these matrices arise in applications.</p>
<p>This evening I gave an example, describing how NASA used a Hadamard matrix of order 32 to transmit photos from the <a href="https://www.johndcook.com/blog/2026/08/13/mariner-hadamard/">Mariner 9</a> spacecraft in 1971. This post will give another application: <strong>sphere packing</strong>.</p>
<p>Conway and Sloane [1] give a correspondence between binary codes and sphere packings that they call Construction A. Given an (<em>n</em>, <em>M</em>, <em>d</em>) binary code <em>C</em>, center a sphere on a point <em>x</em> if and only if <em>x</em> is a congruent (mod 2) to codeword in <em>C</em>.</p>
<p>Here (<em>n</em>, <em>M</em>, <em>d</em>) means an error correcting code that encodes <em>M</em> bits of data as strings of <em>n</em> bits, with a minimum Hamming distance between code words of <em>d</em>, i.e. all codewords differ in at least <em>d</em> bits.</p>
<p>The previous post described how to create a (32, 6, 16) code by stacking a Hadamard matrix <em>H</em> of order 32 on top of −<em>H</em> and turning −1&#8217;s into 0&#8217;s. The analogous construction for a (8, 4, 4) Hadamard code gives <em>E</em><sub>8</sub>, the densest packing in ℝ<sup>8</sup>.</p>
<p>We start with the Hadamard matrix</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/hadamard4.svg" alt="H_8 = \begin{pmatrix} 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 \\ 1 &amp; -1 &amp; 1 &amp; -1 &amp; 1 &amp; -1 &amp; 1 &amp; -1 \\ 1 &amp; 1 &amp; -1 &amp; -1 &amp; 1 &amp; 1 &amp; -1 &amp; -1 \\ 1 &amp; -1 &amp; -1 &amp; 1 &amp; 1 &amp; -1 &amp; -1 &amp; 1 \\ 1 &amp; 1 &amp; 1 &amp; 1 &amp; -1 &amp; -1 &amp; -1 &amp; -1 \\ 1 &amp; -1 &amp; 1 &amp; -1 &amp; -1 &amp; 1 &amp; -1 &amp; 1 \\ 1 &amp; 1 &amp; -1 &amp; -1 &amp; -1 &amp; -1 &amp; 1 &amp; 1 \\ 1 &amp; -1 &amp; -1 &amp; 1 &amp; -1 &amp; 1 &amp; 1 &amp; -1 \end{pmatrix}" width="348" height="189" /></p>
<p>and obtain the matrix</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/hadamard5.svg" alt="M = \begin{pmatrix} 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 \\ 1 &amp; 0 &amp; 1 &amp; 0 &amp; 1 &amp; 0 &amp; 1 &amp; 0 \\ 1 &amp; 1 &amp; 0 &amp; 0 &amp; 1 &amp; 1 &amp; 0 &amp; 0 \\ 1 &amp; 0 &amp; 0 &amp; 1 &amp; 1 &amp; 0 &amp; 0 &amp; 1 \\ 1 &amp; 1 &amp; 1 &amp; 1 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\ 1 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 1 \\ 1 &amp; 1 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 1 \\ 1 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 1 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 1 &amp; 0 &amp; 1 &amp; 0 &amp; 1 \\ 0 &amp; 0 &amp; 1 &amp; 1 &amp; 0 &amp; 0 &amp; 1 &amp; 1 \\ 0 &amp; 1 &amp; 1 &amp; 0 &amp; 0 &amp; 1 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 1 &amp; 1 &amp; 1 \\ 0 &amp; 1 &amp; 0 &amp; 1 &amp; 1 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 1 &amp; 1 &amp; 1 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 1 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 1 \end{pmatrix}" width="255" height="381" /></p>
<p>whose centers form the sphere packing.</p>
<p>This doesn&#8217;t look like the E8 sphere packing as it is usually presented, but it&#8217;s isomorphic.</p>
<p>[1] J. H. Conway and N. J. A. Sloane. Sphere Packings, Lattices and Groups. Springer. 1999.</p>
<p>&nbsp;</p>The post <a href="https://www.johndcook.com/blog/2026/08/13/hadamard-sphere-packing/">Hadamard Codes and Sphere Packing</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How NASA&#8217;s Mariner 9 probe encoded images</title>
		<link>https://www.johndcook.com/blog/2026/08/13/mariner-hadamard/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Thu, 13 Aug 2026 23:54:21 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Coding theory]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247633</guid>

					<description><![CDATA[<p>NASA set Mariner 9 to photograph Mars in 1971. The images had to be encoded for transmission using an error-correcting code, otherwise they would be significantly corrupted when they were received on Earth. The images were encoded for transmission using a code based on Hadamard matrices, specifically a (32, 6, 16) Hadamard code. This means [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/13/mariner-hadamard/">How NASA’s Mariner 9 probe encoded images</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>NASA set Mariner 9 to photograph Mars in 1971. The images had to be encoded for transmission using an error-correcting code, otherwise they would be significantly corrupted when they were received on Earth. </p>
<p>The images were encoded for transmission using a code based on Hadamard matrices, specifically a (32, 6, 16) Hadamard code. This means that each 6-bit pixel value was encoded as a 32-bit code word, with all code words differing in at least 16 positions.</p>
<p>The <a href="https://www.johndcook.com/blog/2026/08/13/constructing-hadamard-matrices/">previous post</a> explained a way to construct Hadamard matrices of order 2<sup><em>n</em></sup>. Use this process to create a 32 &times; 32 Hadamard matrix <em>H</em> and create a 64 &times; 32 matrix <em>M</em> by stacking <em>H</em> on top of &minus;<em>H</em>. Then form a matrix <em>M</em>&prime; by changing all the &minus;1 entries to 0. The rows of <em>M</em>&prime; are the code words. </p>
<p>For a 6-bit photo pixel value, one of the bits determines whether to read a code word from the top half or bottom half of <em>M</em>&prime;. The other five bits determine which row to choose. </p>
<p>So a pixel is transmitted as a 32-bit codeword <em>c</em>, one of the 64 rows of <em>M</em>&prime;. Ideally <em>c</em> would be received, but possibly some corrupted versions <em>c</em>&prime; is received with some of bits flipped. </p>
<p>Replace all the 0&#8217;s in <em>c</em>&prime; with &minus;1 to create <em>c</em>&Prime;. Now multiply <em>M</em> by <em>c</em>&Prime;, thinking of the latter as a column vector. This yields a column vector of length 64. The largest component of this vector corresponds to the row of <em>M</em>&prime; that was most likely sent. </p>
<p>To see this, suppose there was no corruption: <em>c</em> was transmitted and <em>c</em> was received. Then the product <em>M</em><em>c</em>&Prime; has a 32 in the entry corresponding to <em>c</em> and zeros everywhere else. If no more than 7 bits in <em>c</em> were corrupted, the row with the largest entry corresponds to the row that was transmitted. </p>
<p>In practice the product <em>M</em><em>c</em>&Prime; can be computed using an algorithm analogous to the FFT using fewer operations than it would take to multiply a general 64 &times; 32 matrix by a 32 &times; 1 matrix.</p>The post <a href="https://www.johndcook.com/blog/2026/08/13/mariner-hadamard/">How NASA’s Mariner 9 probe encoded images</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Constructing Hadamard matrices</title>
		<link>https://www.johndcook.com/blog/2026/08/13/constructing-hadamard-matrices/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Thu, 13 Aug 2026 15:02:41 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Combinatorics]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247627</guid>

					<description><![CDATA[<p>A Hadamard matrix is an orthogonal matrix whose entries are all either 1 or − 1. For example is a Hadamard matrix of order 2. True to Stigler&#8217;s law of eponymy, James Joseph Sylvester investigated Hadamard matrices before Jacques Hadamard. Sylvester saw how to bootstrap the example above into more examples. If H is a [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/13/constructing-hadamard-matrices/">Constructing Hadamard matrices</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>A Hadamard matrix is an orthogonal matrix whose entries are all either 1 or − 1. For example</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/hadamard2.svg" alt=" \begin{bmatrix} 1 &amp; 1\\ 1 &amp; -1 \end{bmatrix}" width="64" height="48" /></p>
<p>is a Hadamard matrix of order 2. True to <a href="https://www.johndcook.com/blog/2019/01/12/stiglers-law/">Stigler&#8217;s law of eponymy</a>, James Joseph Sylvester investigated Hadamard matrices before Jacques Hadamard. Sylvester saw how to bootstrap the example above into more examples. If <em>H</em> is a Hadamard matrix, then the <a href="https://www.johndcook.com/blog/2025/05/20/partitioned-matrices/">partitioned matrix</a></p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/hadamard3.svg" alt="\begin{bmatrix} H &amp; H\\ H &amp; -H \end{bmatrix}" width="74" height="48" /></p>
<p>Sylvester&#8217;s construction can be generalized as follows. If <em>H</em><sub><em>m</em></sub> is a Hadamard matrix of order <em>m</em> and <em>H</em><sub><em>n</em></sub> is a Hadamard matrix of order <em>n</em>, the the Kronecker product <em>H</em><sub><em>m</em></sub>⊗<em>H</em><sub><em>n</em></sub> is a Hadamard matrix of order <em>mn</em>. That is, you can form a new Hadamard matrix by taking the matrix <em>H</em><sub><em>m</em></sub> and replacing ±1 with the matrix ±<em>H</em><sub><em>n</em></sub>.</p>
<p>Let <em>S</em> be the set of all possible Hadamard matrix orders. By the construction above, this set is closed under multiplication. Since 2 is in <em>S</em>, every power of 2 is in <em>S</em>. Hadamard proved that all <em>n</em> ≥ 4 in <em>S</em> are multiples of 4. That is, the condition 4 | <em>n</em> is necessary. He conjectured that it was also sufficient, though that has not been proven.</p>
<p>So the big question is what is the set <em>S</em>. Is there some multiple of 4 not in S? Until that question is answered, what is the smallest multiple of 4 not <em>known</em> to be in <em>S</em>? Hadamard matrices are useful in applications, so <strong>constructing Hadamard matrices of various orders is useful</strong> even while Hadamard&#8217;s conjecture remains open. For example, see the <a href="https://www.johndcook.com/blog/2026/08/13/mariner-hadamard/">next post</a> for how NASA used Hadamard matrices to transmit photographic images back from Mars.</p>
<h2>Paley&#8217;s method</h2>
<p>Raymond Paley came up with a way of constructing Hadamard matrices of size <em>q</em> + 1 if <em>q</em> is a prime power congruent to 3 mod 4, and of size 2(<em>q</em> + 1) if <em>q</em> is a prime power congruent to 1 mod 4. Let&#8217;s see what we can squeeze out of this.</p>
<p>If <em>p</em> is a prime congruent to 1 mod 4, every power of <em>p</em> is also congruent to 1 mod 4, and so there exist Hadamard matrices of order 2(<em>p</em><sup><em>k</em></sup> + 1) for every <em>k</em>.</p>
<p>If <em>p</em> is a prime with <em>p</em> = 3 mod 4, then even powers of <em>p</em> are congruent to 1 mod 4 and odd powers of <em>p</em> are congruent to 3 mod 4. So there are Hadamard matrices of order 2(<em>p</em><sup>2<em>k</em></sup> + 1) and of order <em>p</em><sup>2<em>k</em>+1</sup> + 1.</p>
<p>Let&#8217;s run a script to see what we can learn from this.</p>
<pre>from sympy import primerange

s = set()

for p in primerange(20):
    if p % 4 == 1:
        s.update([2*(p**k + 1) for k in range(1, 10)])
    if p % 4 == 3:
        s.update([2*(p**(2*k) + 1) for k in range(1, 6)])
        s.update([p**(2*k + 1) + 1 for k in range(1, 6)])
print(sorted(s)[:20])
</pre>
<p>This prints</p>
<pre>12, 20, 28, 36, 52, 100, 164, 244, 252, 340]</pre>
<p>We can add 16 to the list because it&#8217;s a power of 2, and we can add 24 because it&#8217;s 2 × 12, etc. But there doesn&#8217;t seem to be any way to get 44. There <em>is</em> a way to create a Hadamard matrix of order 44, but it doesn&#8217;t follow from anything we&#8217;ve seen so far.</p>
<h2>New records</h2>
<p>I have a book published in 1996 that says Hadamard&#8217;s conjecture had been verified for <em>n</em> up to 428. Until yesterday, the smallest multiple of 4 for which nobody had found a corresponding Hadamard matrix was 668. Then Levent Alpöge announced that he and his and collaborators found an example of size 668 and filled in all remaining gaps below 2000.</p>
<p>So now the set <em>S</em> is known to contain {1, 2, 4, 8, 12, 16, …, 2000}. It also contains all orders that can be obtained by Paley&#8217;s method and other methods. And it contains all products of its elements. But it is not yet known to contain 2004.</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2020/07/22/hadamard-inequality/">Hadamard&#8217;s determinant inequality</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2020/07/11/dirichlet-principle-counterexample/">Hadamard&#8217;s Dirichlet energy example</a></li>
</ul>The post <a href="https://www.johndcook.com/blog/2026/08/13/constructing-hadamard-matrices/">Constructing Hadamard matrices</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Cryptic but consistent</title>
		<link>https://www.johndcook.com/blog/2026/08/12/cryptic-but-consistent/</link>
					<comments>https://www.johndcook.com/blog/2026/08/12/cryptic-but-consistent/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 12 Aug 2026 13:17:03 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247620</guid>

					<description><![CDATA[<p>Suppose you&#8217;ve never worked at the command line and you&#8217;re reading a book about the bash shell. You read that !$ is a shortcut to refer to the last word of the previous command. That little fact will almost certainly not stick in your head for a couple reasons. First, you probably see no need [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/12/cryptic-but-consistent/">Cryptic but consistent</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Suppose you&#8217;ve never worked at the command line and you&#8217;re reading a book about the bash shell. You read that <code>!$</code> is a shortcut to refer to the last word of the previous command. That little fact will almost certainly not stick in your head for a couple reasons. First, you probably see no need for such a shortcut. Second, the syntax seems completely arbitrary.</p>
<p>But then after you use the command line a while, you might begin to notice a pattern. You often have to run a pair of commands with the same last argument, such as when you make a directory then navigate into it.</p>
<pre>
mkdir /some/long/path/name
cd /some/long/path/name
</pre>
<p>Maybe someone sees you typing this and offers a helpful suggestion: you can type <code>!$</code> to repeat the last part of the previous command.</p>
<pre>
mkdir /some/long/path/name
cd !$
</pre>
<p>Once you learn this, you&#8217;ll see uses for it regularly. Sorta like when you buy a green Toyota Corolla and suddenly become aware how many green Toyota Corollas there are out there.</p>
<p>So then you start to use <code>!$</code>, but you have some doubts: is the syntax <code>!$</code> or <code>$!</code>? As long as it&#8217;s just two cryptic symbols, you may have a hard time remembering. </p>
<p>Although the command line is cryptic, it is also consistent. On the command line, and in Unix [1] culture more generally, <code>!</code> refers to a command. For example, you can run a command from inside the Vim text editor with the <code>:!</code> command. And <code>$</code> often refers to the end of something, such as the end of a string in a regex. So you type <code>!</code>, telling the shell that you&#8217;re about to refer to part of a string, then type <code>$</code> to specify that last part.</p>
<p>The characters <code>!$</code> are an example of an <b>event designator</b>, a sort of mini language for referring to parts of commands. The syntax may seem mysterious, but every bit of it is analogous to syntax elsewhere in Unix culture. For example, </p>
<pre>!:s/foo/bar/</pre>
<p>replaces the <em>first</em> instance of <code>foo</code> with <code>bar</code>, and </p>
<pre>!:gs/foo/bar/</pre>
<p>will replace <em>all</em> instances. This is very similar to commands in <code>sed</code> and in <code>vi</code> For more on event designators, see this <a href="https://refp.se/articles/your-shell-and-the-lazy-exclamation-mark">recent article</a> by Filip Roséen.</p>
<p>There&#8217;s a saying that when the student is ready, the teacher will appear [2]. A less woo-woo version of this saying would be that until the student is ready, it doesn&#8217;t matter whether a teacher is there. Once you&#8217;ve used the command line to see a need for various shortcuts, there&#8217;s a much better chance they&#8217;ll stick. </p>
<h2>Related posts</h2>
<ul>
<li class='link'><a href='https://www.johndcook.com/blog/2010/03/03/just-in-case-versus-just-in-time/'>Just-in-case versus Just-in-time</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2026/06/27/brace-expansion-tree/'>Brace expansion</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2026/03/01/tilde-dash/'>Shell variable ~-</a></li>
</ul>
<p>[1] Linux has so thoroughly eclipsed Unix that many people say &#8220;Linux&#8221; when they&#8217;re referring to things inherited from Unix that are now part of Linux and other operating systems, as well as various software packages and programming languages. </p>
<p>Here&#8217;s a plot of references to Unix versus Linux over time, via Google&#8217;s ngram viewer.</p>
<p><img loading="lazy" decoding="async" src="https://www.johndcook.com/unix_linux_ngram.png" width="464" height="214" class="aligncenter size-medium" /></p>
<p>[2] When I first heard this, someone told me it was an Asian proverb. It sure sounds like one. But apparently it comes from a 19th century pastiche of eastern and western ideas.</p>The post <a href="https://www.johndcook.com/blog/2026/08/12/cryptic-but-consistent/">Cryptic but consistent</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/12/cryptic-but-consistent/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Dogs and fat tails</title>
		<link>https://www.johndcook.com/blog/2026/08/11/dogs-and-fat-tails/</link>
					<comments>https://www.johndcook.com/blog/2026/08/11/dogs-and-fat-tails/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Tue, 11 Aug 2026 14:09:46 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Power laws]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247616</guid>

					<description><![CDATA[<p>I was reading a blog post on boat names because it was on Hacker News this morning. The post contained a link to a data set on dog names in NYC and I poked around the data a little. The top names were not at all what I expected, but then again this is limited [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/11/dogs-and-fat-tails/">Dogs and fat tails</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>I was reading a blog post on boat names because it was on Hacker News this morning. The post contained a link to a data set on <a href="https://data.cityofnewyork.us/Health/NYC-Dog-Licensing-Dataset/nu7n-tubp/about_data?ref=beautifulpublicdata.com">dog names in NYC</a> and I poked around the data a little. The top names were not at all what I expected, but then again this is limited to NYC; it&#8217;s not a sample across the US. These were the top 10 names:</p>
<ol>
<li>Bella</li>
<li>Luna</li>
<li>Max</li>
<li>Charlie</li>
<li>Coco</li>
<li>Lola</li>
<li>Rocky</li>
<li>Milo</li>
<li>Teddy</li>
<li>Lucy</li>
</ol>
<p>I wondered if the name frequencies might fit a power-law distribution. They do not, but they follow a log-normal distribution remarkably well.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/dog_name_frequency.png" width="1100" height="800" /></p>
<h2>Related posts</h2>
<ul>
<li class='link'><a href='https://www.johndcook.com/blog/2009/04/16/metabolism-and-power-laws/'>Metabolism and power laws</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2015/03/09/why-isnt-everything-normally-distributed/'>Why isn&#8217;t everything normally distributed?</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2009/08/19/generalized-central-limit-theorem/'>Power laws and the generalized CLT</a></li>
</ul>The post <a href="https://www.johndcook.com/blog/2026/08/11/dogs-and-fat-tails/">Dogs and fat tails</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/11/dogs-and-fat-tails/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Manually unbreakable cryptography</title>
		<link>https://www.johndcook.com/blog/2026/08/11/manually-unbreakable-cryptography/</link>
					<comments>https://www.johndcook.com/blog/2026/08/11/manually-unbreakable-cryptography/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Tue, 11 Aug 2026 12:04:24 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247608</guid>

					<description><![CDATA[<p>Suppose you were able to go back in time, to an era before computers, and give someone contemporary cryptography. Encryption methods that are essentially unbreakable now would certainly be unbreakable then. But there&#8217;s a catch: not only do attackers not have computers, neither do users. Manual cryptography If you told someone about RSA encryption, for [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/11/manually-unbreakable-cryptography/">Manually unbreakable cryptography</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Suppose you were able to go back in time, to an era before computers, and give someone contemporary cryptography. Encryption methods that are essentially unbreakable now would certainly be unbreakable then. But there&#8217;s a catch: not only do attackers not have computers, neither do users.</p>
<h2>Manual cryptography</h2>
<p>If you told someone about RSA encryption, for example, you&#8217;d lose them right after you said &#8220;First you find a couple 1000-digit primes.&#8221; But there&#8217;s no need for using 1000-digit primes if no attacker has a computer. You could use 100 digit primes. Could you use 10 digit primes? If you chose primes just big enough to make the method unbreakable by hand, could someone implement it by hand?</p>
<p>Kirchoff&#8217;s principle says the strength of an encryption method should depend only on keeping the key secret, not the method. If you <em>could</em> keep the method secret, RSA would be unbreakable because nobody thought of anything like it before computers. But to make our thought experiment more interesting, let&#8217;s suppose that an enemy has also traveled back in time. If you tell your side about RSA, he can tell his side about it as well. So we&#8217;re back to Kirchoff&#8217;s principle.</p>
<p>An encryption method combinining substitution and permutation would have been practical to carry our manually. The <a href="https://www.johndcook.com/blog/2020/02/22/adfgvx/">ADFGVX</a> cipher from 1918 was a start in this direction. That idea could been extended further, with a larger substitution set and longer permutations, and with more than one round of substitution and permutation, approaching what would be come the approach used in modern symmetric encryption. Such a method might have been manually implementable without being manually breakable.</p>
<h2>Mechanized cryptography</h2>
<p>World War II was a time of transition from manual cryptography to computerized cryptography. Encryption machines were attacked by cryptanalysis machines, though these machines were general-purpose computers. If you could implement a symmetric encryption method like AES in a mechanical device, no mechanical device could break it.</p>
<p>You could use something like <a href="https://www.johndcook.com/blog/2020/04/04/feistel-networks/">DES</a>, simpler than AES but still unbreakable at the time. DES is considered broken because now you could throw enough compute power at it to break it by brute force, but that would not be possible with only mechanical devices.</p>
<p>My hunch is that the best approach would be stream ciphers. Maybe it would be practical to implement one of these by hand or with the aid of simple calculating machines. Something like PCG, which is not cryptographically secure today [1], would have been then, though I don&#8217;t know how practical it would have been to carry out PCG, say, in the 1940s.</p>
<h2>More pre-computer cryptography</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2021/08/19/vigenere/">Vigenère cipher</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2023/02/27/playfair-cipher/">Playfair cipher</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2024/01/25/straddling-checkerboard-encryption/">Straddling checkerboard</a></li>
</ul>
<p>[1] In 2020, Charles Bouillaguet, Florette Martinez,<span class="s1"> </span>and Julia Sauvage were able to break PCG using 20,000 CPU-hours. See their paper Practical seed-recovery for the PCG Pseudo-Random Number Generator. IACR Transactions on Symmetric Cryptology. ISSN 2519-173X, Vol. 2020, No. 3, pp. 175–196.</p>The post <a href="https://www.johndcook.com/blog/2026/08/11/manually-unbreakable-cryptography/">Manually unbreakable cryptography</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/11/manually-unbreakable-cryptography/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Learning from historical mistakes</title>
		<link>https://www.johndcook.com/blog/2026/08/10/learning-from-historical-mistakes/</link>
					<comments>https://www.johndcook.com/blog/2026/08/10/learning-from-historical-mistakes/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Mon, 10 Aug 2026 14:34:21 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247605</guid>

					<description><![CDATA[<p>The following extraordinary paragraph comes from Knuth&#8217;s TAOCP Volume 4A, right before the last set of exercises. Many of the exercises below ask a modern reader to find and/or to correct errors in the literature of bygone days. The point is not to gloat over how smart we are in the 21st century; the point [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/10/learning-from-historical-mistakes/">Learning from historical mistakes</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>The following extraordinary paragraph comes from Knuth&#8217;s TAOCP Volume 4A, right before the last set of exercises.</p>
<blockquote><p>Many of the exercises below ask a modern reader to find and/or to correct errors in the literature of bygone days. The point is not to gloat over how smart we are in the 21st century; the point is rather to understand that even the pioneers of a subject can stumble. One good way to learn that a set of ideas is not really as simple as it might seem to today&#8217;s computer scientists and mathematicians is to observe that some of the world&#8217;s leading thinkers had to struggle with the concepts when they were new.</p></blockquote>The post <a href="https://www.johndcook.com/blog/2026/08/10/learning-from-historical-mistakes/">Learning from historical mistakes</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/10/learning-from-historical-mistakes/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Inverse differential equations</title>
		<link>https://www.johndcook.com/blog/2026/08/10/inverse-differential-equations/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Mon, 10 Aug 2026 14:32:42 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Differential equations]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247603</guid>

					<description><![CDATA[<p>In science and engineering classes, you might describe a system using Newton&#8217;s laws and end up with a differential equation. You then solve the differential equation, analytically or numerically, to see how the solutions behave. You might also do the opposite, especially in a mathematics class: look at what differential equation a set of functions [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/10/inverse-differential-equations/">Inverse differential equations</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>In science and engineering classes, you might describe a system using Newton&#8217;s laws and end up with a differential equation. You then solve the differential equation, analytically or numerically, to see how the solutions behave.</p>
<p>You might also do the opposite, especially in a mathematics class: look at what differential equation a set of functions satisfy in order to understand those functions.</p>
<p>Bessel functions came out of solving differential equations from <a href="https://www.johndcook.com/blog/2026/06/06/from-kepler-to-bessel/">astronomy</a>. But then they turned out to be useful, not just in other areas of science, but in pure mathematics as well. So there are Bessel function users who came to the functions first and haven&#8217;t seen the differential equation they came from.</p>
<p>You can learn a lot about Bessel functions, and other special functions, by looking at their defining differential equation even if you&#8217;re not directly interested in the differential equation or the physical problem that motivated it.</p>
<p>Bessel functions satisfy</p>
<p style="padding-left: 40px;"><em>x</em>² <em>y</em>″ + <em>x</em> <em>y</em>′ + (<em>x</em>² − <em>n</em>²) <em>y</em> = 0.</p>
<p>You can tell a lot about Bessel functions just by inspecting this equation without solving it. If we divide by <em>x</em>² and write the equation in the form</p>
<p style="padding-left: 40px;"><em>y</em>″ + (<em>p</em>(<em>x</em>)/<em>x</em>) <em>y</em>′ + (<em>q</em>(<em>x</em>)/<em>x</em>²) <em>y </em>= 0</p>
<p>then <em>p</em>(<em>x</em>) = 1 and <em>q</em>(<em>x</em>) = <em>x</em>² − <em>n</em>². The indicial equation</p>
<p style="padding-left: 40px;"><em>r</em>(<em>r</em> − 1) + <em>p</em>(0) <em>r</em> + <em>q</em>(0) = 0</p>
<p>reduces to</p>
<p style="padding-left: 40px;"><em>r</em>² = <em>n</em>²</p>
<p>and so <em>r</em> = ±<em>n</em>. That alone tells us there are two solutions, one analytic at zero and one singular at zero. These are <em>J</em><sub><em>n</em></sub> and <em>Y</em><sub><em>n</em></sub> respectively. It also tells us the behavior of these functions as <em>x</em> goes to zero and as <em>x</em> goes to infinity. To find out more, look up &#8220;method of Frobinius.&#8221;</p>The post <a href="https://www.johndcook.com/blog/2026/08/10/inverse-differential-equations/">Inverse differential equations</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>DNA and Bessel functions</title>
		<link>https://www.johndcook.com/blog/2026/08/09/dna-and-bessel-functions/</link>
					<comments>https://www.johndcook.com/blog/2026/08/09/dna-and-bessel-functions/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sun, 09 Aug 2026 17:17:42 +0000</pubDate>
				<category><![CDATA[Science]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247593</guid>

					<description><![CDATA[<p>I was reading a book on the history of the discovery of the structure of DNA [1] and was surprised by a few passing references to Bessel functions. According to Claude, When X-rays are diffracted by a helical structure, the resulting diffraction pattern breaks into a series of horizontal &#8220;layer lines.&#8221; Cochran, Crick, and Vand [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/09/dna-and-bessel-functions/">DNA and Bessel functions</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>I was reading a book on the history of the discovery of the structure of DNA [1] and was surprised by a few passing references to Bessel functions.</p>
<p>According to Claude,</p>
<blockquote><p>When X-rays are diffracted by a helical structure, the resulting diffraction pattern breaks into a series of horizontal &#8220;layer lines.&#8221; Cochran, Crick, and Vand showed mathematically that the diffracted amplitude on the <em>n</em>-th layer line is proportional to a Bessel function of the first kind, order <em>n</em>:</p>
<p style="padding-left: 40px;"><em>J</em><sub><em>n</em></sub>(2π <em>r R</em>)</p>
<p>where <em>r</em> is the radius of the helix and <em>R</em> is the distance out from the center (the meridian) in the diffraction pattern.</p></blockquote>
<p>The citation for this paragraph is a paper from 1952 [2] that amazingly is behind a paywall.</p>
<p><strong>Update</strong>: Evan pointed out something fishy in the expression above: &#8220;Isn’t there a dimensional problem with <em>J</em>(2π <em>r</em> <em>R</em>)? Maybe 2π<em>r</em>/<em>R</em> instead?&#8221;</p>
<p>This was Claude&#8217;s response:</p>
<ul>
<li><strong>r</strong> is the radius of the helix, a real-space length (say, in Å).</li>
<li><strong>R</strong> is the radial coordinate in <strong>reciprocal space</strong> — it has units of inverse length (Å⁻¹), because that&#8217;s how X-ray diffraction/Fourier space works (spatial frequency, not distance).</li>
</ul>
<p>So Evan and Claude were both right. There is an implicit division happening, but crystallographers do write <em>r R</em>.</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2026/06/05/mr-bessels-eponymous-functions/">Mr. Bessel’s eponymous functions</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2026/06/06/from-kepler-to-bessel/">From Kepler to Bessel</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2024/01/31/bessel-zero-spacing/">Bessel zero spacing</a></li>
</ul>
<p>[1] Watson and Crick didn&#8217;t &#8220;discover DNA&#8221; as is commonly said. DNA was discovered in 1878. Watson and Crick discovered the <em>structure</em> of DNA in 1953.</p>
<p>[2] Cochran, W., Crick, F. H. C., &amp; Vand, V. (1952). &#8220;The Structure of Synthetic Polypeptides. I. The Transform of Atoms on a Helix.&#8221; Acta Crystallographica, 5(5), 581–586.</p>The post <a href="https://www.johndcook.com/blog/2026/08/09/dna-and-bessel-functions/">DNA and Bessel functions</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/09/dna-and-bessel-functions/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>A simple range reduction method</title>
		<link>https://www.johndcook.com/blog/2026/08/09/simple-range-reduction/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sun, 09 Aug 2026 16:46:59 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247580</guid>

					<description><![CDATA[<p>At the end of my post on how not to calculate cosine I said that the first step in calculating cosine, particularly cosine of a large number, would be to do range reduction. This post will present a simple range reduction method by Cody and Waite that is adequate for moderately large arguments. If you [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/09/simple-range-reduction/">A simple range reduction method</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>At the end of my post on <a href="https://www.johndcook.com/blog/2026/08/07/how-not-to-calculate-cos/">how not to calculate cosine</a> I said that the first step in calculating cosine, particularly cosine of a large number, would be to do range reduction. This post will present a simple range reduction method by Cody and Waite that is adequate for moderately large arguments.</p>
<p>If you want to compute the sine or cosine of an angle <em>x</em> you could start by reducing <em>x</em> mod 2π since that would not change the result. However, accurately reducing a number mod 2π is not trivial; that&#8217;s why range reduction is an area of algorithm development.</p>
<h2>Range reduction mod π/2</h2>
<p>Even better would be to reduce <em>x</em> mod π/2. Reducing to a smaller range means that power series method, and other methods such as rational approximation, will be more efficient.</p>
<p>So suppose you can find an integer <em>k</em> such that</p>
<p style="padding-left: 40px;"><em>x</em> − <em>k</em> π/2 = <em>y</em></p>
<p>where 0 ≤ <em>y</em> ≤ π/2. Then sin(<em>x</em>) is ±sin(<em>y</em>) or ±cos(<em>y</em>), depending on <em>k</em> mod 4 equals 0, 1, 2, or 3.</p>
<pre>from math import *

def reduced_sin(x, k):
     match k % 4:
        case 0: return sin(x)
        case 1: return cos(x)
        case 2: return -sin(x)
        case 3: return -cos(x)
</pre>
<h2>Naive range reduction</h2>
<p>Now let&#8217;s set <em>x</em> = 500. Then <em>k</em> = 318 because that&#8217;s the multiple of π/2 we need to subtract to bring <em>x</em> into range, and the sine of <em>x</em> should be the negative of the sine of the reduced value <em>y</em> because 318 = 2 mod 4.</p>
<p>The following code computes sin(<em>x</em>) with naive range reduction</p>
<pre>def naive_sin(x):
    k = floor(x / (pi/2))
    y = x % (pi/2)
    return reduced_sin(y, k)
</pre>
<p>and when <em>x</em> = 500 the error is on the order of 1.7 × 10<sup>−14</sup>.</p>
<h2>Better range reduction</h2>
<p>The value of <em>k</em> above is fine, but we&#8217;d like to calculate <em>y</em> more accurately. The following code is much better.</p>
<pre>def Cody_Waite_sin(x):
    C1 = 1686629713 / 2**30
    C2 = 4701928774853425 / 2**86

    k = floor(x / (pi/2))
    y = (x - k*C1) - k*C2
    return reduced_sin(y, k)
</pre>
<p>This will compute sin(500) to full machine precision. What kind of magic is this?</p>
<p>The trick is that the exact value of C1 + C2 equals π/2 to more precision than is possible in a single float [1]. You can confirm, with <em>bc</em> or some other extended precision software, that the difference between C1 + C2 and π/2 is roughly 2<sup>−88</sup>, while the limit of float precision is 2<sup>−52</sup>.</p>
<p>If we compute</p>
<pre>y = x - k*(C1 + C2)</pre>
<p>then we&#8217;re doing the same calculation as <code>naive_sin</code> and will get the same error. But if we compute</p>
<pre>y = (x - k*C1) - k*C2</pre>
<p>we will get a more accurate result, provided <em>x</em> isn&#8217;t too large.</p>
<p>You can use the following code to play around and see how large <em>x</em> can be before errors start to creep in. For small enough <em>x</em>, like 500, the Cody and Waite sine returns full precision. For larger <em>x</em> it&#8217;s better than naive sine but does not return full precision. And for large enough <em>x</em> it completely breaks down.</p>
<pre>def compare(x):
    y0 = naive_sin(x) 
    y1 = Cody_Waite_sin(x)
    y2 = sin(x)
    print("Naive error:     ", y2 - y0)
    print("Cody Waite error:", y2 - y1)
</pre>
<p>Now this may seem circular since we&#8217;re using <code>math.sin</code> as our gold standard. However, this function is calling the sine function on your CPU, which is using sophisticated range reduction to compute its result accurately down to the last bit, assuming you run the code on a computer that&#8217;s less than 40 years old.</p>
<p>The Cody and Waite algorithm is inadequate for large <em>x</em>, but it&#8217;s a good place to begin studying range reduction. It shows there are clever ways of squeezing out more precision than seems possible.</p>
<p>&nbsp;</p>
<p>[1] The numerator <em>n</em><sub>1</sub> of C1 is ⌊2<sup>30</sup> π/2⌋. The numerator <em>n</em><sub>2</sub> of C2 is the solution to</p>
<p style="padding-left: 40px;">2<sup>86−30</sup> <em>n</em><sub>1</sub> + <em>n</em><sub>2</sub> = ⌊2<sup>86</sup> π/2⌋.</p>The post <a href="https://www.johndcook.com/blog/2026/08/09/simple-range-reduction/">A simple range reduction method</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Corrupted apostrophes</title>
		<link>https://www.johndcook.com/blog/2026/08/07/corrupted-apostrophes/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sat, 08 Aug 2026 01:20:25 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Unicode]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247576</guid>

					<description><![CDATA[<p>I have a program that shares files between my laptop and my phone. It works well, except for apostrophes. When I type an apostrophe ' on my laptop, it becomes â€&#x2122; on my phone. And when I type 's on my phone, it becomes 痴 on my laptop. Apparently the phone turns the apostrophe (U+0027) [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/07/corrupted-apostrophes/">Corrupted apostrophes</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>I have a program that shares files between my laptop and my phone. It works well, except for apostrophes.</p>
<p>When I type an apostrophe <code>'</code> on my laptop, it becomes <code>â€&#x2122;</code> on my phone. And when I type <code>'s</code> on my phone, it becomes <code>痴</code> on my laptop.</p>
<p>Apparently the phone turns the apostrophe (U+0027) into a right single quote (U+2019), then bungles bytes in the UTF-8 encoding of U+2019 as three Windows-1252 characters. The bytes E28099<sub>hex</sub> are interpreted as <code>â</code> (E2<sub>hex</sub>), <code>€</code> (80<sub>hex</sub>), and <code>&#x2122;</code> (99<sub>hex</sub>).</p>
<p>When I type <code>'s</code> on my phone, it is encoded as two Windows-1252 characters 92<sub>hex</sub> and 73<sub>hex</sub>. Then by the time the text appears on my laptop, the bytes 9273<sub>hex</sub> are interpreted as a Shift-JIS encoding of the CJK character <code>痴</code> (U+75F4).</p>
<p>Here&#8217;s Python code to reproduce the problem.</p>
<pre>
def mojibake(s: str, n: int, bad_encoding: str = 'cp1252') -> str:
    for _ in range(n):
        s = s.encode('utf-8').decode(bad_encoding, errors='replace')
    return s

print(mojibake("’s", 1))
print(mojibake("’s", 1, 'shift_jis'))
</pre>
<p>The code won&#8217;t corrupt ASCII text. The problem started with an ASCII character being replaced by a similar non-ASCII character. Text containing a non-ASCII character gets more corrupted with each round.</p>The post <a href="https://www.johndcook.com/blog/2026/08/07/corrupted-apostrophes/">Corrupted apostrophes</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How not to calculate cosine</title>
		<link>https://www.johndcook.com/blog/2026/08/07/how-not-to-calculate-cos/</link>
					<comments>https://www.johndcook.com/blog/2026/08/07/how-not-to-calculate-cos/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Fri, 07 Aug 2026 15:11:10 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Math]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247572</guid>

					<description><![CDATA[<p>Calculus professors with no experience in numerical computing will tell students that computers calculate trig functions with power series. They don&#8217;t. I worked on the implementation of trig functions in hardware, and I can assure you we didn&#8217;t just use power series. Power series are an excellent way to calculate functions near the center of [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/07/how-not-to-calculate-cos/">How not to calculate cosine</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Calculus professors with no experience in numerical computing will tell students that computers calculate trig functions with power series. They don&#8217;t. I worked on the implementation of trig functions in hardware, and I can assure you we didn&#8217;t just use power series.</p>
<p>Power series are an excellent way to calculate functions <em>near the center of the series</em>, such as computing <a href="https://www.johndcook.com/blog/2010/07/27/sine-approximation-for-small-x/">sine for small angles</a>. But the further you get from the center, the less useful power series are.</p>
<p>Let&#8217;s suppose you want to calculate cos(200) using the power series for cosine. The <em>n</em>th term of that series is</p>
<p style="padding-left: 40px;">(−1)<sup><em>n</em></sup> <em>x</em><sup>2<em>n</em></sup> / (2<em>n</em>)!</p>
<p>This is an alternating series, and so the error in truncating the series after <em>n</em> terms is bounded by the size of the <em>n</em>+1 term, <em>if</em> you&#8217;ve gone far enough out in the series that the terms are monotonically decreasing in absolute value.</p>
<p>To calculate cos(200) to machine precision, i.e. with an error of less than 2<sup>−52</sup>, we&#8217;d need to sum the series up to <em>n</em> where</p>
<p style="padding-left: 40px;">| 200<sup>2<em>n</em>+2</sup> / (2<em>n</em> + 2)! | &lt; 2<sup>−52</sup></p>
<p>Actually, that will ensure that the <em>absolute</em> error is small enough, but not that the <em>relative</em> error is small enough; if the value of cos(200) is small, we&#8217;d need more terms. Let&#8217;s ignore that and assume we&#8217;re only concerned with absolute error.</p>
<p>Turns out we&#8217;d need 287 terms. That&#8217;s a lot of terms. But you might say &#8220;That&#8217;s fine. I&#8217;m not in a hurry, and it&#8217;s just more work for the computer, not for me.&#8221; OK, so let&#8217;s try.</p>
<pre>from math import *

s = 0
for n in range(288):
    s += (-1)**n * 200**(2*n) / factorial(2*n)
print(s)
</pre>
<p>This prints -3.6840358571084123e+67. You may suspect the answer is incorrect since values of cosine are on the order of 1, not on the order of 10<sup>67</sup>. Something went spectacularly bad. On closer inspection, it&#8217;s remarkable the code didn&#8217;t crash.</p>
<p>If you changed <code>200</code> to <code>200.0</code> above, the code would crash. Calculating <code>200.0**(2*n)</code> overflows when <em>n</em> = 67. But when we calculate <code>200**(2*n)</code>, the result is an integer. And we&#8217;re dividing by <code>factorial(2*n)</code>, which is also an integer. Both of these integers become too large to fit in a float, but their <em>ratio</em> has a maximum value of around 10<sup>80</sup>, smaller than the maximum float, which is on the order of 10<sup>308</sup>.</p>
<p>When we don&#8217;t overflow, we have a different problem: catastrophic cancellation. You can&#8217;t calculate a number between −1 and 1 as an alternating sum of numbers as large as 10<sup>80</sup>. You&#8217;d need more than 80 + 16 = 96 decimal places of precision to compute the sum accurately, and floating point only gives you between 15 and 16 decimal places of precision.</p>
<p>So how <em>would</em> you calculate cos(200)? The first step would be to use some sort of range reduction on 200. You could reduce 200 mod 2π to get a smaller number to work with.</p>
<pre>&gt;&gt;&gt; from math import cos, pi
&gt;&gt;&gt; x = 200 % (2*pi)
&gt;&gt;&gt; x
5.221255477432827
</pre>
<p>Using a power series to compute the cosine of 5.221255477432827 is feasible, but not optimal. There&#8217;s also another problem: the naive range reduction above loses some precision.</p>
<pre>&gt;&gt;&gt; cos(x)
0.48718767500701254
&gt;&gt;&gt; cos(x) - cos(200)
6.661338147750939e-15
</pre>
<p>The error is small, but it&#8217;s still an order of magnitude larger than machine precision. You can&#8217;t simply reduce <em>n</em> mod 2π with ordinary float division because the integer part of <em>n</em> / 2π pushes some digits of precision off the right end. I intend to write about how range reduction works in future posts.</p>
<p><strong>Update</strong>: See <a href="https://www.johndcook.com/blog/2026/08/09/simple-range-reduction/">this post</a> for a simple range reduction algorithm that is fine for values of <em>x</em> such as 200, but not adequate for much larger values.</p>The post <a href="https://www.johndcook.com/blog/2026/08/07/how-not-to-calculate-cos/">How not to calculate cosine</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/07/how-not-to-calculate-cos/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>cos(200!)</title>
		<link>https://www.johndcook.com/blog/2026/08/07/cos200/</link>
					<comments>https://www.johndcook.com/blog/2026/08/07/cos200/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Fri, 07 Aug 2026 13:19:07 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247561</guid>

					<description><![CDATA[<p>In a footnote to the previous post, I said that Python&#8217;s math library can calculate the logarithm of extremely large numbers but not the cosine. This post will expand on that comment. In this post I&#8217;ll use n = 200! as my example rather than 1000! because this value of N is larger than the [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/07/cos200/">cos(200!)</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>In a footnote to the <a href="https://www.johndcook.com/blog/2026/08/06/log1000/">previous post</a>, I said that Python&#8217;s math library can calculate the logarithm of extremely large numbers but not the cosine. This post will expand on that comment.</p>
<p>In this post I&#8217;ll use <em>n</em> = 200! as my example rather than 1000! because this value of <em>N</em> is larger than the largest representable floating point number but small enough to be more convenient to work with.</p>
<p>Suppose someone calculates 200! for you:</p>
<pre>78865786736479050355236321393218506229513597768717326329474253324435\
94499634033429203042840119846239041772121389196388302576427902426371\
05061926624952829931113462857270763317237396988943922445621451664240\
25403329186413122742829485327752424240757390324032125740557956866022\
60319041703240623517008587961789222227896237038973747200000000000000\
00000000000000000000000000000000000
</pre>
<p>You could now calculate log(<em>n</em>) using</p>
<p style="padding-left: 40px;"><em>n</em> = 7.886578673647905 × 10<sup>374</sup></p>
<p>and so</p>
<p style="padding-left: 40px;">log(<em>n</em>) = log(7.886578673647905 × 10<sup>374</sup>)<br />
= log(7.886578673647905) + 374 log(10) = 863.2319871924055.</p>
<p>The key thing that makes this possible is that the least significant digits of <em>n</em> only affect the least significant digits of log(<em>n</em>). In the calculation above I kept the first 16 digits of <em>n</em>. Python couldn&#8217;t make use of any more digits, and had no need of any more digits, in order to produce the logarithm to machine precision.</p>
<p>Cosine doesn&#8217;t work that way. The cosine of <em>n</em> depends on the remainder when <em>n</em> is divided by 2π, and that remainder depends on every single digit of <em>n</em>. I&#8217;ll illustrate that below.</p>
<p>Using <code>bc -l</code> and setting the scale to 400, I can calculated <em>n</em> then calculate</p>
<p style="padding-left: 40px;">cos(<em>n</em> + 10<sup><em>i</em></sup>)</p>
<p>for i running from 0 to 374, tweaking each digit one at a time. (Except when a digit is a 9 and the addition results in a carry.)</p>
<pre>    n = 1
    for (i = 1; i &lt;= 200; i++) n *= i
    scale = 400
    for (i = 1; i &lt;= 374; i++) {
        x = c(n+10^i)
        scale = 16
        print x/1, "\n"
        scale = 400
    }
</pre>
<p>Here&#8217;s what a plot of the results look like.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/cos200factorial1.png" width="480" height="360" /></p>
<p>The value of cos(<em>n</em>) is about −0.985, but the values above are all over the map. We can look at the range by projecting all the points over to the left edge then rotating a quarter turn:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/cos200factorial2.png" width="360" height="15" /></p>
<p>The remarkable thing about this image is that there are a few gaps, i.e. a few values the cosine does <em>not</em> take on.</p>
<p>Here&#8217;s a more sophisticated way to look at it. The sequence 10<sup><em>i</em></sup> mod 2π is dense in [0, 2π], and so by going far enough out in the sequence, we can find a value that shifts the phase of <em>n</em> by any desired amount within any given tolerance.</p>
<p>Every digit in <em>n</em> matters, and changing any digit can change the value of cosine to be essentially any value. You cannot calculate the cosine of an enormous number without using some kind of extended precision arithmetic. There are clever range reduction algorithms that minimize the amount of extended arithmetic necessary, but extended arithmetic cannot be completely eliminated.</p>The post <a href="https://www.johndcook.com/blog/2026/08/07/cos200/">cos(200!)</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/07/cos200/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Calculating log(1000!)</title>
		<link>https://www.johndcook.com/blog/2026/08/06/log1000/</link>
					<comments>https://www.johndcook.com/blog/2026/08/06/log1000/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Thu, 06 Aug 2026 13:23:43 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247553</guid>

					<description><![CDATA[<p>The previous post pointed out that the following code such as the following unexpectedly works. &#62;&#62;&#62; from math import log, factorial &#62;&#62;&#62; log(factorial(1000)) 5912.128178488163 If you don&#8217;t find this unexpected, note that if you replace math.log with numpy.log the code will fail [1]. Functions like natural logarithm operate on real numbers. Real numbers are represented [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/06/log1000/">Calculating log(1000!)</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>The <a href="https://www.johndcook.com/blog/2026/08/05/math-log/">previous post</a> pointed out that the following code such as the following unexpectedly works.</p>
<pre>&gt;&gt;&gt; from math import log, factorial
&gt;&gt;&gt; log(factorial(1000))
5912.128178488163
</pre>
<p>If you don&#8217;t find this unexpected, note that if you replace <code>math.log</code> with <code>numpy.log</code> the code will fail [1]. Functions like natural logarithm operate on real numbers. Real numbers are represented as floating point numbers in programming languages, and 1000! factorial is too large to represent as a standard floating point number. (More on that <a href="https://www.johndcook.com/blog/2009/04/06/anatomy-of-a-floating-point-number/">here</a>.)</p>
<p>In this post I&#8217;d like to look at how you might calculate log(1000!) with less capable software, and even without software.</p>
<p>One approach would be to sum the logarithms of the numbers 1 through 1000. This will give essentially the same result as above, with a little difference in the last couple decimal places due to rounding error.</p>
<p>If you have a way to calculate 1000! but not a way to cast it to a floating point number, you could do this manually.</p>
<pre>&gt;&gt;&gt; s = str(factorial(1000))
&gt;&gt;&gt; s[:16]
'4023872600770937'
&gt;&gt;&gt; len(s)
2568
</pre>
<p>This tells us 1000! = 4.023872600770937 × 10<sup>2567</sup>. Therefore</p>
<p style="padding-left: 40px;">log(1000!) = log(4.023872600770937) + 2567 log(10)</p>
<p>which only requires working with numbers of modest size.</p>
<h2>Calculating by hand</h2>
<p>Now suppose it&#8217;s 1964. You don&#8217;t have a computer, or even a calculator, but you do have a copy of the recently published Handbook of Mathematical Functions by Abramowitz and Stegun (A&amp;S). You turn to Table 6.6 &#8220;Factorials for large arguments.&#8221; This has values of factorial for 100, 200, 300, …, 1000, so you can simply look up your answer to 20 decimal places.</p>
<p>That was too easy; I didn&#8217;t expect that to be there when I started writing this post. If you wanted to compute log(950!), for example, you&#8217;d have to work harder. You could find A&amp;S equation 6.1.41 (Stirling&#8217;s series) which says</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/AS6.1.41.svg" alt="\begin{align*} \ln \Gamma(z) &amp;\sim (z - \tfrac{1}{2}) \ln z - z + \tfrac{1}{2} \ln 2\pi + \frac{1}{12z} - \frac{1}{360z^3} \\ &amp;+ \frac{1}{1260z^5} - \frac{1}{680z^7} + \cdots \end{align*}" width="401" height="90" /></p>
<p>So how would you use this formula to calculate log(1000!)? Since <em>n</em>! = Γ(<em>n</em> + 1), you set <em>z</em> = 1001.</p>
<p>You&#8217;d need to decide how many terms you need to use. Assuming the error is on the order of the first term you leave out, you&#8217;d reason that you could probably stop with the 1/12<em>z</em> term because the next term is between 10<sup>−11</sup> and 10<sup>−12</sup>.</p>
<p>You find Table 4.2 has natural logarithms, but not for 1001. You can look up log(1.001), however, and at the bottom of the same page is log(10) to 16 decimal places, and you can find log(10) to 24 decimal places in Table 1.1. So you calculate</p>
<p style="padding-left: 40px;">log(1001) = log(1.001 × 10³) = log(1.001) + 3 log(10).</p>
<p>You can find log(2) and log(π) in Table 1.1, and average them to find ½ log(2π).</p>
<p>Here&#8217;s Python code to simulate the hand calculations.</p>
<pre>log2     = 0.6931_47180_55994_53094_172321 # Table 1.1
log10    = 2.3025_85092_99404_56840_179915 # Table 1.1
logpi    = 1.1447_29885_84940_01741_43427  # Table 1.1
log1_001 = 0.00099_95003_330835            # Table 4.2

z = 1001
logz = log1_001 + 3*log10
s = (z - 0.5)*logz - z + (log2 + logpi)/2 + 1/(12*z)

print(s)
</pre>
<p>This result differs from the one at the top of the post only in the last decimal place.</p>
<h2>Related posts</h2>
<p>Doing calculations with tables is not as simple as &#8220;just look it up.&#8221; It takes a bit of skill.</p>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2024/06/03/using-a-table-of-logarithms/">Using a table of logarithms</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2024/06/25/trig-tables/">Using a trig table</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2026/03/26/table-precision/">How much precision can you squeeze out of a table?</a></li>
</ul>
<p>[1] The code will also fail if you replace <code>math.log</code> with <code>math.cos</code>. Both logarithm and cosine return moderate sized real numbers when given enormous inputs like 1000!, so representing the output as a float is not the problem. But logarithms of huge numbers can be computed with ordinary precision functions, as above. But computing the cosine of a huge number requires extended precision.</p>
<p><strong>Update</strong>: The <a href="https://www.johndcook.com/blog/2026/08/07/cos200/">next post</a> expands on why computing the cosine of a large number is more difficult than computing the log.</p>The post <a href="https://www.johndcook.com/blog/2026/08/06/log1000/">Calculating log(1000!)</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/06/log1000/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>The code that didn&#8217;t break</title>
		<link>https://www.johndcook.com/blog/2026/08/05/math-log/</link>
					<comments>https://www.johndcook.com/blog/2026/08/05/math-log/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 05 Aug 2026 18:26:25 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247547</guid>

					<description><![CDATA[<p>Last week I wrote a post on hiding cryptographic keys in decks of cards. I wrote some code for that post that shouldn&#8217;t work, but before fixing I noticed that it in fact did work. The code computes logarithms for integers larger than the largest representable float. For example, the largest float is on the [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/05/math-log/">The code that didn’t break</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Last week I wrote a <a href="https://www.johndcook.com/blog/2026/07/28/keys-and-cards/">post</a> on hiding cryptographic keys in decks of cards. I wrote some code for that post that shouldn&#8217;t work, but before fixing I noticed that it in fact did work.</p>
<p>The code computes logarithms for integers larger than the largest representable float. For example, the largest float is on the order of 10<sup>308</sup>, and yet the following code works.</p>
<pre>&gt;&gt;&gt; import math
&gt;&gt;&gt; math.log10(10**400)
400.0
</pre>
<p>The <code>log</code>, <code>log2</code>, and <code>log10</code> functions have some code inside that handles large integers specially. It doesn&#8217;t simply convert the integers to floats before taking the logarithm. If it did, it would overflow. If you replace <code>math</code> with <code>numpy</code> above, the code will fail. NumPy&#8217;s implementation of logarithms is more what I would expect.</p>
<p>While playing around with this I also noticed that you can define floats larger than the largest float without warnings.</p>
<pre>&gt;&gt;&gt; math.log(1e308)
709.1962086421661
&gt;&gt;&gt; math.log(1e309)
inf
</pre>
<p>This isn&#8217;t a feature of <code>math.log</code> but of how Python handles scientific notation. The expression <code>1e308</code> is the floating point representation of 10<sup>308</sup>. It is a float, not an int.</p>
<pre>&gt;&gt;&gt; type(1e308)
&lt;class 'float'&gt;
</pre>
<p>The expression <code>1e309</code> is also a float. But since it&#8217;s larger than is possible for a float, Python interprets it as <code>inf</code>. The code</p>
<pre>math.log(1e309)</pre>
<p>returns <code>inf</code> based on the reasoning that log(∞) = ∞.</p>
<p>That explains the following behavior:</p>
<pre>&gt;&gt;&gt; 1e309 == 1e310
True
</pre>
<p>The expressions <code>1e309</code> and <code>1e310</code> are equal because both are alternate ways of writing <code>inf</code>.</p>The post <a href="https://www.johndcook.com/blog/2026/08/05/math-log/">The code that didn’t break</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/05/math-log/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Enumerating trees and circles</title>
		<link>https://www.johndcook.com/blog/2026/08/05/enumerating-trees-and-circles/</link>
					<comments>https://www.johndcook.com/blog/2026/08/05/enumerating-trees-and-circles/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 05 Aug 2026 14:49:35 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247540</guid>

					<description><![CDATA[<p>A few days ago I wrote a post on counting rooted trees. That post looked at the sequence c(n) which counts the number of rooted trees with n nodes. Here one node is distinguished as the root, but the nodes below the root are not distinguished from each other; all that matters is how the [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/05/enumerating-trees-and-circles/">Enumerating trees and circles</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>A few days ago I wrote a post on <a href="https://www.johndcook.com/blog/2026/08/01/counting-rooted-trees/">counting rooted trees</a>. That post looked at the sequence <em>c</em>(<em>n</em>) which counts the number of rooted trees with <em>n</em> nodes. Here one node is distinguished as the root, but the nodes below the root are not distinguished from each other; all that matters is how the nodes are connected.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" style="background-color: white;" src="https://www.johndcook.com/rooted_trees_order_1_to_4.svg" width="680" height="600" /></p>
<p>The number of rooted trees with <em>n</em> nodes is the same as the number of ways to configure <em>n</em> − 1 non-overlapping circles. Not only are the counts the same, there is a natural correspondence between the trees and the circles. It&#8217;s not obvious that there should be such a correspondence, with the right notation the correspondence is sort of a pun.</p>
<p>The standard way to represent unlabeled trees is as a <a href="https://www.johndcook.com/blog/2022/10/26/multisets/">multiset</a> of their children. We use a multiset, not a set, because some elements will be repeated. We represent a leaf as a pair of parentheses: <code>()</code>.</p>
<p>There is only one rooted tree with one node: <code>()</code>.</p>
<p>There is only one rooted tree with one two nodes: <code>(())</code>. Here the outer parentheses represent the root node and the inner parentheses represent its child.</p>
<p>There are two rooted trees with three nodes, and we can represent them as <code>((()))</code> and <code>((),())</code>. The first is the straight line tree: a node that has a single child node that has a single child node. The second is a node that branches to two nodes. (Here&#8217;s where we need multisets.)</p>
<p>The four rooted trees with four nodes can be represented as <code>(((())))</code>, <code>((((),()))</code>, <code>((),(()))</code>, and <code>((),(),(),())</code>.</p>
<p>Here are the nine rooted trees with five nodes:</p>
<pre>((((()))))
((((),())))
(((),(())))
(((),(),()))
((()),(()))
((),((())))
((),((),()))
((),(),(()))
((),(),(),())
</pre>
<p>The correspondence with non-overlapping circles removes the outer parentheses then joins the rest to form circles, with nested parentheses corresponding to concentric circles. A more geometric way to see the correspondence is to start at the bottom of the tree, replace leaves with circles, then work your way up circling connected components.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/nonoverlapping_circles2.png" width="362" height="896" /></p>The post <a href="https://www.johndcook.com/blog/2026/08/05/enumerating-trees-and-circles/">Enumerating trees and circles</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/05/enumerating-trees-and-circles/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
	</channel>
</rss>
