← Module hub · Self-check · Your local record

Unit 3: Meet the Bernoulli numbers

Draft Item 2: What A Language Model Does Differently Item 4: Ask AI To Generate The Routine 37 min
DEVELOPMENT REVIEW DEPLOYMENT - NOT READY FOR RELEASE

Video

Media Pending: Unit Video

Intended content: Full narrated video presentation, including visual assets, caption file, and transcript.

Learning purpose: Separates two different traps: the two modern `B1` sign

Planned form & duration: Video, ~6 minutes.

Production state: Draft (awaiting final audio/video assembly and YouTube upload).

Accessible text alternative: Disagreements in AI output often stem from unspoken convention mismatches rather than pure computational failure. The written material below covers the same complete learning path.

Watch what changes

Two rows of Bernoulli values are compared index by index. At n=0 both read 1 and agree. At n=1 the oracle reads minus one half and the submitted routine reads plus one half; this is the first divergence and it is marked in red. Every later index agrees again, but the comparison stops at the first disagreement because it is a precise place to begin debugging; it does not prove the cause of any later mismatch.
Two number lines run across the frame, one above the other. The upper line is modern Bernoulli indexing: B0 = 1, B1 = -1/2, B2 = 1/6, B3 = 0, B4 has a value to derive, B5 = 0, B6 = 1/42, B7 = 0, and B8 is withheld. The lower line begins as an exact copy, aligned index for index. Then the lower line changes. The three zero terms at B3, B5 and B7 fall away, each marked with the word 'zero', because Note G numbers only the non-zero terms. The first two terms, 1 and -1/2, fall away too, marked 'not numbered in Note G', because Note G's numbering begins at 1/6. Four terms remain. They are renumbered as Ada's B1, B3, B5 and B7, and the labels visibly slide one place to the right as they arrive, so the two lines are no longer in step. The animation ends with Ada's B7 highlighted directly beneath the modern B8, and the statement that Note G computes Ada's B7, which is the modern B8: the same symbol, two different terms, because the modern B7 is 0.

Reading time: about 11 minutes. Activity: about 20 minutes. Course items: see course/course-map.md for items 2 and 4.

What you should be able to do afterwards

  1. Say, in plain terms, what a Bernoulli number is and where the sequence comes from.
  2. Derive B4 from the recurrence, by hand, and show your working.
  3. Explain why two correct-looking programs can disagree about B1, and say which convention this module uses.
  4. Translate between Lovelace's Note G labels and modern indices.

Why this unit comes before the AI unit

In Unit 4 you will ask an AI system to produce a routine that returns Bernoulli numbers. It will produce something. It will look competent. Generated code almost always does.

The question that decides whether that output is useful to you is not "does this look right" but "what should the answer be". If you cannot answer the second question independently, you have no way of answering the first. So this unit gives you the independent answer first, deliberately, before anything is generated.

This ordering is the whole point of the module's approach to critical thinking: build enough understanding to judge, then use the tool.

What a Bernoulli number is

The Bernoulli numbers are a fixed sequence of exact rational numbers — ordinary fractions — with one value for each whole-number index from 0 upwards. They are written B0, B1, B2, and so on.

They are not approximations, not estimates, and not a matter of taste. Given the index, the value is completely determined. That property is what makes them a good subject for this module: there is a right answer, it can be written down exactly, and disagreement can always be resolved.

Here is the sequence this module works with.

n B_n n B_n
0 1 10 5/66
1 -1/2 12 -691/2730
2 1/6 14 7/6
3 0 16 -3617/510
4 derive in the activity 18 43867/798
6 1/42 20 -174611/330
8 shown after your derivation 30 8615841276005/14322

All odd B_n for n > 1 are exactly zero. That is not a rounding artefact or a convenient approximation; those values are zero, precisely.

Two things are worth noticing before you read on. First, the values do not shrink tidily — B14 is larger than B12, and B30 is enormous. Second, the denominators are already awkward by B12. Both facts matter later: a routine that returns decimals will look plausible for small indices and drift once the numbers grow.

Where the sequence comes from

You do not need this section to complete the unit. It is here so the numbers do not feel as though they were invented for the exercise.

Ask a simple question: what is 1² + 2² + … + 9²? The answer is 285, and you can get it by adding nine numbers. But there is also a closed formula that gives the answer for any upper limit, without adding anything up. There is another for cubes, another for fourth powers, and so on.

Write those formulas in a single general form covering every power at once, and the same sequence of fractions appears in the coefficients each time. That sequence is the Bernoulli numbers. They were studied in the seventeenth and early eighteenth centuries and were long-established mathematics by the time Ada Lovelace selected them as the subject of Note G. For sources on Note G itself, see course/references.md.

The rule that generates them

Every Bernoulli number is fixed by the ones before it, through one identity:

sum_{j=0}^{n} C(n+1, j) * B_j = 0

C(n+1, j) is the binomial coefficient — "n plus one choose j" — the numbers from Pascal's triangle. For a given n, the identity gives you a sum of terms, all of them known except the last, which contains B_n. Substitute what you know, and solve.

Starting from B0 = 1, this generates the whole sequence, one value at a time, in a fixed order, with no judgement required at any step. It is an ordered procedure in exactly the sense of Unit 1.

Worked example: B2

Take n = 2. The identity gives three terms:

C(3,0)·B0 + C(3,1)·B1 + C(3,2)·B2 = 0

The binomial coefficients for n + 1 = 3 are 1, 3, 3. Substituting B0 = 1 and B1 = -1/2:

(1)(1) + (3)(-1/2) + (3)(B2) = 0

Work the known part first:

1 - 3/2 = -1/2

So:

-1/2 + 3·B2 = 0
        3·B2 = 1/2
          B2 = 1/6

Which is what the table says. Notice what you did not need: a calculator, a computer, or anyone's assurance. You needed the rule, the earlier values, and care with fractions.

In the activity you will do the same for B4, where n = 4 gives five terms instead of three. That is the derivation checkpoint cp03-b4-by-hand, and it is worth doing before you read further into this page. Stop here, open the activity, and attempt Task 1 from your own working. The rest of this reading is placed behind a labelled disclosure on the course site because it contains the result.

Continue after attempting Task 1 in the activity

Trap 1 — there are two conventions

Here is a scenario you will meet in Unit 5. Two programs both claim to compute Bernoulli numbers. They agree on every value except one. One says B1 = -1/2, the other says B1 = +1/2. Everything else — B2 = 1/6, B4 = -1/30, all of it — is identical.

Neither program has a bug.

There are two established conventions for this sequence:

B0 B1 B2 B4 B6
First Bernoulli numbers 1 -1/2 1/6 -1/30 1/42
Second Bernoulli numbers 1 +1/2 1/6 -1/30 1/42

Both are standard, both are published, and they differ in exactly one value. Which one you want depends on which formula you are feeding it into; neither is more correct than the other in the abstract.

This module fixes the first convention: B1 = -1/2. That is what the reference implementation in course/lab/reference_bernoulli.py returns, it is what the checker enforces, and it is a clause you will write into a prompt in Unit 6.

The lesson generalises well beyond Bernoulli numbers. When two competent sources disagree, the first thing to check is not who made a mistake but whether they were answering the same question. A specification that omits a convention has not made the convention go away; it has only made the disagreement harder to diagnose. In Unit 5 this failure mode has a name: b1-sign.

Trap 2 — Ada's indexing is not ours

The second trap is historical, and it is easier to walk into.

Since every odd Bernoulli number above B1 is zero, Lovelace does not give those zeros a label. She numbers only the values that are actually present. Her label numbers are therefore one smaller: her Bk is the modern B(k+1):

Ada's label modern index value
B1 B2 1/6
B3 B4 -1/30
B5 B6 1/42
B7 B8 -1/30

Note G's worked example computes Ada's B7, which in modern notation is B8 = -1/30.

This mapping is shown only after the derivation task because two rows contain the same numerical value as B4. The checkpoint tests whether you can produce that value from the recurrence, not whether you can find it in a later table.

Nothing here is an error on Lovelace's part. It is a different notation that happens to use identical symbols, which is exactly what makes it hazardous. A generated routine can be a faithful reading of Note G and a broken modern component at the same time. Historical fidelity and specification compliance are not the same requirement, and a routine can fail by being right about the wrong century. In Unit 5 this failure mode is named ada-indexing.

The mapping is also available in code, in the oracle: ada_to_modern_index and modern_to_ada_index.

Two routes to verification

The activity offers two routes. They carry equal weight, cover the same checkpoints, and are marked the same way, which is to say not at all.

Table-based verification. Derive B4 on paper from the recurrence, then compare a claimed set of values against the table above, index by index. This is what a reviewer does when they have a document rather than a program: line up the claim against the reference and look for the first place they part company. Reading a specification against a known-good table is a professional technique in its own right, not a reduced version of running the code.

Python with exact rationals. Do the same comparison in code, using fractions.Fraction from the standard library. Nothing to install.

from fractions import Fraction

b0 = Fraction(1)
b1 = Fraction(-1, 2)
b2 = Fraction(1, 6)

print(b0 + 3 * b1)        # the known part of the n = 2 identity

Use Fraction, not float. float would give you 0.16666666666666666 for B2, which is not 1/6 and will not compare equal to it. For small indices the difference is invisible; by B30 it is not. Exact arithmetic is a requirement of this module's interface contract, not a stylistic preference.

Terms used here

  • Convention — a choice that is fixed by agreement rather than derived, such as B1 = -1/2. Two people following different conventions can both be right and still disagree.
  • Exact rational arithmetic — computing with fractions as numerator and denominator, so no rounding occurs. Python's fractions.Fraction does this.
  • Oracle — a trusted reference you compare an answer against. Here, course/lab/reference_bernoulli.py.

These also appear in course/glossary.md.

Check yourself

This unit has three checkpoints:

  • cp03-b4-by-hand — derive B4 from the recurrence
  • cp03-convention — identify which convention a program is using
  • cp03-ada-index — translate a Note G label into a modern index

Run them by either route:

python3 selfcheck.py run cp03-b4-by-hand    # or use the browser self-check

For cp03-b4-by-hand, a wrong answer will not show you the right one. It will name the specific slip your answer looks like and give you the next step. That is deliberate: deriving the value is the objective, so handing it over would remove the exercise.

Work through it

Timings: video 6 min, reading 11 min, activity 20 min.

Check yourself

This unit has 3 checkpoints. Both routes ask the same questions and accept the same answers — use whichever suits you.

In a terminal, from course/lab/:

python3 selfcheck.py run --unit 3

Your local record

Local progress is available in a supported browser.

Before this unit