Prime numbers has been a most beloved number category from the ancient years until now. The Greek
Euclides proves in his 9th book that prime numbers are infinite and
later, around 250 B.C. Eratosthenes invents a method
(Eratosthene's Sieve) which finds all prime numbers smaller than a
given number.
Next big step: Piere Fermat believes that all
numbers of the form Fn = 22n +1
are prime. In the 18th century Euler disproves it by showing that F5
is divided by 641. Next step is again by Euler who in 1742, finds a
relation between the harmonic series (1 + 1/2 + 1/3 + ... + 1/∞)
and the sum of the inverse prime number series (1/2 + 1/3 + 1/5
+ ... + 1/p).
The next contribution is in 1798, when
Andrien-Marie Legendre in his "Essai sur la theorie des nombres", he
suggests without proving it, that for relatively big "x" values, the
number of primes less or equal than "x" is approximated by p(x)
= x /(log(x) - 1.08366). Indeed, here's a sample:
x = 10166, p(x) = 1248.412109, actual = 1248, diff =
0.412
x = 10167, p(x) = 1248.519897, actual = 1248, diff = 0.520
x = 10168, p(x) = 1248.627563, actual = 1248, diff = 0.628
x = 10169, p(x) = 1248.735352, actual = 1249, diff = -0.265
x = 10170, p(x) = 1248.843018, actual = 1249, diff = -0.157
x = 10171, p(x) = 1248.950684, actual = 1249, diff = -0.049
x = 10172, p(x) = 1249.058472, actual = 1249, diff = 0.058
x = 10173, p(x) = 1249.166138, actual = 1249, diff = 0.166
x = 10174, p(x) = 1249.273926, actual = 1249, diff = 0.274
x = 10175, p(x) = 1249.381592, actual = 1249, diff = 0.382
Note: You can find the C code producing these samples at
the end of the writeup.
That is, there are 1249 prime numbers in the range
[2, 10172] for example, and the approximation formula yields
1249.058472. Of course, as "x" gets bigger and bigger, the interval
between successing primes gets bigger, so the approximation is not
always that good. Example:
x = 11410, p(x) = 1381.592535, actual = 1376, diff =
5.593
x = 11411, p(x) = 1381.698959, actual = 1377, diff = 4.699
x = 11412, p(x) = 1381.805382, actual = 1377, diff = 4.805
x = 11413, p(x) = 1381.911804, actual = 1377, diff = 4.912
x = 11414, p(x) = 1382.018225, actual = 1377, diff = 5.018
In 1792, Gauss observing that in fixed-length
intervals of positive integers, primes appear with decreased
frequency as the beginning of the interval is increasing, suggested
the approximation formula p(x) = ∫x2(dt/log
t) which is better in some ranges but worse than that of
Legendre. For example, for the same as above range [10166, 10175],
Gauss's formula yields far bigger divergions:
x = 10166, diff = -15.099
x = 10167, diff = -15.208
x = 10168, diff = -15.316
x = 10169, diff = -14.424
x = 10170, diff = -14.533
x = 10171, diff = -14.641
x = 10172, diff = -14.749
x = 10173, diff = -14.858
x = 10174, diff = -14.966
x = 10175, diff = -15.075
In other ranges, of course, the approximation is
much better than the one that Legendre's formula calculates.
Lattely, research is focused on the properties of
the difference pn+1 - pn, where pn is
some prime and pn+1 the next prime. A sample of this
sequence is:
1, 2, 2, 4, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, where
for example, the first element "1" is the difference of the first prime
("2") and the very next ("3"). The prime number distribution is closely related with one unsolved till now problem: Goldbach's conjecture.
C code for the examples
(is_prime(x) and other useful functions for number
theory problems, can be found at Useful Number Theory functions in C)
Gauss approximation formula:
p(x) = ∫x2(dt/log
t)
#include <stdio.h>
#include <math.h>
int is_prime(int x)
{
int i, s;
if (x < 2) return 0;
for (i = 2, s = sqrt(x); i <= s; i++)
if (x % i == 0) return 0;
return 1;
}
int primes_till_x(int x){
unsigned int i, sum = 0;
for(i=1; i <= x;i++)
if (is_prime(i)) sum++;
return sum;
}
int main(){
unsigned int x;
double t, d=0.001, integr;
for(x=10166; x <= 10175; x++){
integr = 0.0;
for(t=2; t <= x; t += d)
integr += d/(log(t));
printf("x = %d, diff = %.3f\n", x, primes_till_x(x)- integr);
}
return 0;
}
Legendre approximation formula:
p(x) = x /(log(x) -
1.08366)
#include <stdio.h>
#include <math.h>
int is_prime(int x)
{
int i, s;
if (x < 2) return 0;
for (i = 2, s = sqrt(x); i <= s; i++)
if (x % i == 0) return 0;
return 1;
}
int main(){
unsigned int i;
double tt1, tt2=0.0;
for(i=1;i <= 10175; i++){
tt1=i/(log(i)-1.08366);
if (is_prime(i)) tt2 +=1;
// printf("x = %d, p(x) = %.6f, actual = %.0f, diff = %.3f\n", i, tt1, tt2, tt1-tt2);
printf("%d %.3f\n", i, tt1-tt2);
}
return 0;
}
Bibliography:
The Papyros Larousse Britannica Encyclopedia.