`⎕io←0`

throughout.

I was re-reading *A Mathematician’s Apology* before recommending it to Suki Tekverk, our summer intern, and came across a statement that the number of primes less than `1e9`

is `50847478`

(§14, page 23). The function `pco`

from the dfns workspace does computations on primes; `¯1 pco n`

is the number of primes less than `n`

:

```
)copy dfns pco
¯1 pco 1e9
50847534
```

The two numbers `50847478`

and `50847534`

cannot both be correct. A search of `50847478`

on the internet reveals that it is incorrect and that `50847534`

is correct. `50847478`

is erroneously cited in various textbooks and even has a name, Bertelsen’s number, memorably described by MathWorld as “an erroneous name erroneously given the erroneous value of `π(1e9) = 50847478`

.”

Although several internet sources give `50847534`

as the number of primes less than `1e9`

, they don’t provide a proof. Relying on them would be doing the same thing — arguing from authority — that led other authors astray, even if it is the authority of the mighty internet. Besides, I’d already given Suki, an aspiring mathematician, the standard spiel about the importance of proof.

How *do* you prove the `50847534`

number? One way is to prove correct a program that produces it. Proving `pco`

correct seems daunting — it has 103 lines and two large tables. Therefore, I wrote a function from scratch to compute the number of primes less than `⍵`

, a function written in a way that facilitates proof.

```
sieve←{
b←⍵⍴{∧⌿↑(×/⍵)⍴¨~⍵↑¨1}2 3 5
b[⍳6⌊⍵]←(6⌊⍵)⍴0 0 1 1 0 1
49≥⍵:b
p←3↓{⍵/⍳⍴⍵}∇⌈⍵*0.5
m←1+⌊(⍵-1+p×p)÷2×p
b ⊣ p {b[⍺×⍺+2×⍳⍵]←0}¨ m
}
+/ sieve 1e9
50847534
```

`sieve ⍵`

produces a boolean vector `b`

with length `⍵`

such that `b/⍳⍴b`

are all the primes less than `⍵`

. It implements the sieve of Eratosthenes: mark as not-prime multiples of each prime less than `⍵*0.5`

; this latter list of primes obtains by applying the function recursively to `⌈⍵*0.5`

. Some obvious optimizations are implemented:

- Multiples of
`2 3 5`

are marked by initializing`b`

with`⍵⍴{∧⌿↑(×/⍵)⍴¨~⍵↑¨1}2 3 5`

rather than with`⍵⍴1`

. - Subsequently, only odd multiples of primes
`> 5`

are marked. - Multiples of a prime to be marked start at its square.

Further examples:

```
+/∘sieve¨ ⍳10
0 0 0 1 2 2 3 3 4 4
+/∘sieve¨ 10*⍳10
0 4 25 168 1229 9592 78498 664579 5761455 50847534
```

There are other functions which are much easier to prove correct, for example, `sieve1←{2=+⌿0=(⍳3⌈⍵)∘.|⍳⍵}`

. However, `sieve1`

requires `O(⍵*2)`

space and `sieve1 1e9`

cannot produce a result with current technology. (Hmm, a provably correct program that cannot produce the desired result …)

We can test that `sieve`

is consistent with `pco`

and that `pco`

is self-consistent. `pco`

is a model of the p: primitive function in J. Its cases are:

` pco n `

the `n`

-th prime

`¯1 pco n `

the number of primes less than `n`

` 1 pco n `

`1`

iff `n`

is prime

` 2 pco n `

the prime factors and exponents of `n`

` 3 pco n `

the prime factorization of `n`

`¯4 pco n `

the next prime `< n`

` 4 pco n `

the next prime `> n`

`10 pco r,s `

a boolean vector `b`

such that `r+b/⍳⍴b`

are the primes in the half-open interval `[r,s)`

.

```
¯1 pco 10*⍳10 ⍝ the number of primes < 1e0 1e1 ... 1e9
0 4 25 168 1229 9592 78498 664579 5761455 50847534
+/ 10 pco 0 1e9 ⍝ sum of the sieve between 0 and 1e9
50847534
⍝ sum of sums of 10 sieves
⍝ each of size 1e8 from 0 to 1e9
+/ t← {+/10 pco ⍵+0 1e8}¨ 1e8×⍳10
50847534
⍝ sum of sums of 1000 sieves
⍝ each of size 1e6 from 0 to 1e9
+/ s← {+/10 pco ⍵+0 1e6}¨ 1e6×⍳1000
50847534
t ≡ +/ 10 100 ⍴ s
1
⍝ sum of sums of sieves with 1000 randomly
⍝ chosen end-points, from 0 to 1e9
+/ 2 {+/10 pco ⍺,⍵}/ 0,({⍵[⍋⍵]}1000?1e9),1e9
50847534
¯1 pco 1e9 ⍝ the number of primes < 1e9
50847534
pco 50847534 ⍝ the 50847534-th prime
1000000007
¯4 pco 1000000007 ⍝ the next prime < 1000000007
999999937
4 pco 999999937 ⍝ the next prime > 999999937
1000000007
4 pco 1e9 ⍝ the next prime > 1e9
1000000007
⍝ are 999999937 1000000007 primes?
1 pco 999999937 1000000007
1 1
⍝ which of 999999930 ... 1000000009
⍝ are prime?
1 pco 999999930+4 20⍴⍳80
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1
+/∘sieve¨ 999999937 1000000007 ∘.+ ¯1 0 1
50847533 50847533 50847534
50847534 50847534 50847535
```