Number Theory · Visualisation · Math
📅 April 2026 ⏱ ≈ 12 min read 🎯 Beginner–Intermediate

Numbers & Spirals: Number Theory in Pixels

Prime numbers look random — yet arrange the integers in a spiral and primes align along diagonals. The Fibonacci sequence looks arbitrary — yet sunflowers and pine cones pack seeds using exactly those numbers. Number theory, the oldest branch of pure mathematics, has a secret visual life. This article takes prime sieves, spirals, and phyllotaxis from integers to pixels with fast JavaScript canvas implementations.

1. Primes and the Sieve of Eratosthenes

A prime number is an integer greater than 1 with no positive divisors other than 1 and itself. The Sieve of Eratosthenes (≈240 BCE) is one of the oldest algorithms in existence: mark all multiples of 2, 3, 5, … in sequence; the unmarked numbers are prime.

Sieve procedure up to N: 1. Initialise boolean array A[2…N] = true 2. For p = 2, 3, 4, …, √N: if A[p] is true (p is prime): mark A[p²], A[p²+p], A[p²+2p], … as false 3. Return all i with A[i] = true

Time complexity: O(N log log N) // remarkably fast Space complexity: O(N)

The inner loop starts at p² — all smaller multiples of p were already eliminated by earlier primes. The segmented sieve reduces memory to O(√N) by processing the range in cache-friendly blocks.

2. The Ulam Spiral

Stanisław Ulam discovered the spiral bearing his name by accident in 1963, doodling during a conference talk. Write the integers 1, 2, 3, … in an outward-going spiral pattern on a square grid; mark the positions of all prime numbers; the result shows unmistakeable diagonal lines of primes.

The diagonals correspond to quadratic polynomials of the form n² + n + 41 (Hardy-Ramanujan formula) which produce a disproportionate density of primes for small n. The visual structure hints that prime distribution is not purely random — a pattern which connects to deep unresolved questions in analytic number theory.

Sacks spiral: a polar variant where the integer n is placed at angle θ = 2π√n (arc-length spaced on an Archimedean spiral). Prime positions form striking radial rays and arches, making the quasi-periodicity of primes much clearer than the Ulam square spiral.

3. Prime-Counting Function and the PNT

Let π(x) denote the number of primes ≤ x (note: this π is not the constant 3.14…). The Prime Number Theorem (Hadamard & de la Vallée Poussin, 1896) states:

π(x) ~ x / ln(x) as x → ∞

Better approximation: Li(x) = ∫₂^x 1/ln(t) dt (logarithmic integral)

|π(x) − Li(x)| ~ √x / (4π) · ln(x) (Riemann's estimate, assuming RH)

Plotting π(x), x/ln(x), and Li(x) together visually demonstrates how the three curves track each other — and how Li(x) is a much tighter approximation.

4. Fibonacci Sequence and the Golden Ratio

The Fibonacci sequence 1, 1, 2, 3, 5, 8, 13, 21, … is defined by the recurrence F(n) = F(n-1) + F(n-2). The ratio of consecutive terms converges to the golden ratio φ:

φ = (1 + √5) / 2 = 1.6180339887…

lim_{n→∞} F(n+1) / F(n) = φ

Closed form (Binet formula): F(n) = (φⁿ − ψⁿ) / √5 where ψ = (1 − √5)/2 ≈ −0.618

φ is algebraically the "most irrational" number — its continued fraction representation [1; 1, 1, 1, …] converges as slowly as possible. This property is key to understanding why plants use Fibonacci angles.

5. Phyllotaxis and the Sunflower Spiral

Sunflower seeds, pine cone scales, and daisy petals are arranged in two families of interlocking spirals. The number of clockwise and counter-clockwise spirals are almost always consecutive Fibonacci numbers (13 and 21, 34 and 55, …).

This pattern arises from simple growth: each successive seed or leaf is placed at a fixed angular increment α relative to the previous one. The optimal packing (each seed as far as possible from its neighbours) occurs when α equals the golden angle:

golden angle = 360° × (1 − 1/φ) = 360° / φ² ≈ 137.508°

Equivalently: 2π × (2 − φ) radians = 2π(1 − 1/φ) ≈ 2.399 rad

Any irrational multiple of 360° would avoid exact overlap, but the golden angle is irrational in the most extreme sense — meaning the density of seeds is maximally uniform and two families of spirals form whose counts are consecutive Fibonacci numbers.

6. JavaScript: Sieves, Spirals, and Sunflowers

Segmented Sieve of Eratosthenes

// Returns a Uint8Array: sieve[i] = 1 if i is prime, 0 otherwise
function sieve(N) {
  const s = new Uint8Array(N + 1).fill(1);
  s[0] = s[1] = 0;
  for (let p = 2; p * p <= N; p++)
    if (s[p])
      for (let j = p * p; j <= N; j += p) s[j] = 0;
  return s;
}
const s = sieve(1_000_000);
console.log('Primes ≤ 1 000 000:', s.reduce((a, v) => a + v, 0));  // 78498

Ulam Spiral on Canvas

// Draw an Ulam spiral of given size on a canvas
function drawUlam(canvas, N) {
  const W = canvas.width, H = canvas.height;
  const ctx = canvas.getContext('2d');
  const cs = Math.floor(Math.min(W, H) / N);  // cell size in px
  const isPrime = sieve(N * N);

  ctx.fillStyle = '#000'; ctx.fillRect(0, 0, W, H);
  ctx.fillStyle = '#f59e0b';

  // Walk the spiral: right, up, left, down, right, …
  const dirs = [[1,0],[0,-1],[-1,0],[0,1]];
  let x = Math.floor(N / 2), y = Math.floor(N / 2), d = 0, seg = 1, step = 0, turn = 0;
  for (let n = 1; n <= N * N; n++) {
    if (isPrime[n]) ctx.fillRect(x * cs, y * cs, cs, cs);
    x += dirs[d][0]; y += dirs[d][1]; step++;
    if (step === seg) {
      step = 0; d = (d + 1) % 4; turn++;
      if (turn % 2 === 0) seg++;
    }
  }
}

Sunflower Phyllotaxis

function drawSunflower(canvas, nSeeds = 1000, c = 6) {
  const ctx  = canvas.getContext('2d');
  const cx   = canvas.width  / 2;
  const cy   = canvas.height / 2;
  const gold = Math.PI * (3 - Math.sqrt(5));  // golden angle in radians ≈ 2.3998
  ctx.fillStyle = '#000'; ctx.fillRect(0, 0, canvas.width, canvas.height);

  for (let i = 0; i < nSeeds; i++) {
    const r   = c * Math.sqrt(i);           // radius proportional to √i
    const theta = gold * i;                  // golden angle increment
    const x   = cx + r * Math.cos(theta);
    const y   = cy + r * Math.sin(theta);
    const rad = Math.max(1.5, Math.sqrt(i) * 0.1);
    ctx.beginPath(); ctx.arc(x, y, rad, 0, Math.PI * 2);
    ctx.fillStyle = `hsl(${40 + i * 0.04}, 90%, 65%)`;
    ctx.fill();
  }
}

7. The Riemann Hypothesis — a Glimpse

The Riemann zeta function is defined for complex s with Re(s) > 1 as:

ζ(s) = Σₙ₌₁^∞ 1/nˢ = ∏_{p prime} 1/(1 − p^{-s}) (Euler product)

Riemann showed how ζ(s) relates to the exact formula for π(x) via the non-trivial zeros — complex numbers ρ = ½ + it where ζ(ρ) = 0. The Riemann Hypothesis (1859) conjectures that all non-trivial zeros lie on the critical line Re(s) = ½.

If true, it would prove the tightest possible error bounds on the prime-counting function: |π(x) − Li(x)| < (1/8π) √x ln(x) for all x ≥ 2.657. More than 10¹³ zeros have been verified to lie on the critical line, but the conjecture remains one of the Millennium Prize Problems — unsolved since 1859.

Plotting the Riemann zeta function on the critical line as an Argand diagram trajectory reveals a beautiful spiral structure: the complex values of ζ(½ + it) wind around the origin, crossing zero whenever a non-trivial zero occurs.

8. Further Number Theory Visualisations

Dirichlet Characters and Quadratic Residues

Plot n mod p for varying integers n along a grid, colouring cells by whether the result is a quadratic residue mod p. The resulting images exhibit striking geometric symmetry rooted in the theory of Legendre symbols and L-functions.

Totient and Euler's Function

Plotting Euler's totient function φ(n) — the count of integers up to n coprime to n — against n reveals a cloud with fractal density structure. The ratio φ(n)/n approximates the probability that a randomly chosen integer is coprime to n.

Farey Sequences and Stern-Brocot Tree

The Stern-Brocot tree arranges all positive fractions in a binary tree such that every rational appears exactly once in lowest terms. Zooming in on the tree boundary reveals self-similar structure corresponding to the Minkowski question-mark function — a continuous, strictly increasing function that maps rationals to dyadic rationals.

🔢 Open Number Spirals →