Helianthus sunflowerianumleg. cstef, 7.x.2026
Sunflowers have math in them, wtf?
How to pack as many seeds as possible into a sunflower head: Fibonacci
In the middle of a sunflower, if you look hard enough, you’ll see two families of spirals, one turning clockwise and the other counterclockwise . Count each one and you usually get two approximate Fibonacci numbers, like 55 or 66. It looks like the plant calculating it, which can seem a bit absurd. It actually isn’t counting anything (duh), it’s just following one dumb rule for the sake of efficiency and the numbers appear on their own.
The dumb rule
A sunflower grows new seeds one at a time at the centre and shoves the older ones outwards. Each new seed goes a fixed angle, say , around from the previous one. The question is now: which angle packs it best?
Think of as a fraction of a full turn. If that fraction is a ratio of small integers, say or , the seeds stack into a few straight spokes with ugly gaps between them.
Typst source
#import "@preview/cetz:0.5.2": canvas, draw
#let angle = 360deg * 2 / 5 // 2/5 of a turn
#let arms = 5
#let seeds = 150
#let head-radius = 3.5
#let c = head-radius / calc.sqrt(seeds) // seed n sits at radius c * sqrt(n)
#let seed = c / 2 // dot radius
#let palette = theme.series.slice(0, 3)
#canvas({
draw.circle((0, 0), radius: head-radius + seed, stroke: (paint: theme.line, dash: "dashed"))
for n in range(1, seeds + 1) {
let r = c * calc.sqrt(n)
draw.circle(
(r * calc.cos(n * angle), r * calc.sin(n * angle)),
radius: seed,
fill: palette.at(calc.rem(calc.rem(n, arms), palette.len())),
stroke: none,
)
}
})
You want the fraction that stays away from lining up for as long as possible, and that’s the golden ratio:
It’s the hardest number to approximate with fractions, because its continued fraction is nothing… but ones.
The golden angle
Turn a full circle by and you get the golden angle:
Fibonacci appears because the ratio of consecutive terms of converges to :
So the best rational approximations to the golden angle come from Fibonacci numbers, and those are the spiral counts you see in the head.
Placing the seeds
Seed sits at angle . Its distance from the center grows with the square root of , keeping the area per seed constant. A disc of radius has area , so if each seed takes area , then seeds fill
With , the coordinates are:
Typst source
#import "@preview/cetz:0.5.2": canvas, draw
#let phi = (1 + calc.sqrt(5)) / 2
#let angle = 360deg / calc.pow(phi, 2)
#let arms = 21
#let seeds = 400
#let head-radius = 3.4
#let c = head-radius / calc.sqrt(seeds) // seed n sits at radius c * sqrt(n)
#let seed = c / 2 // dot radius
#let palette = theme.series.slice(0, 3)
#canvas({
for n in range(1, seeds + 1) {
let r = c * calc.sqrt(n)
draw.circle(
(r * calc.cos(n * angle), r * calc.sin(n * angle)),
radius: seed,
fill: palette.at(calc.rem(calc.rem(n, arms), palette.len())),
stroke: none,
)
}
})
Typst source
#import "@preview/cetz:0.5.2": canvas, draw
#let phi = (1 + calc.sqrt(5)) / 2
#let angle = 360deg / calc.pow(phi, 2)
#let arms = 34
#let seeds = 400
#let head-radius = 3.4
#let c = head-radius / calc.sqrt(seeds) // seed n sits at radius c * sqrt(n)
#let seed = c / 2 // dot radius
#let palette = theme.series.slice(0, 3)
#canvas({
for n in range(1, seeds + 1) {
let r = c * calc.sqrt(n)
draw.circle(
(r * calc.cos(n * angle), r * calc.sin(n * angle)),
radius: seed,
fill: palette.at(calc.rem(calc.rem(n, arms), palette.len())),
stroke: none,
)
}
})
That’s pretty much it! If you want to see more, check out this video on the golden ratio by Numberphile :D