The Prime Numbers, Part 2
The Prime Numbers, Part 2
The fundamental theorem of arithmetic says that every integer greater than
1 can be written as a product of primes, and furthermore there is only one
way to do it except for the ordering of the factors.
How can we actually find the prime factorization of a given integer n > 1?
The simplest and most naive approach goes as follows. Given n, find the
smallest non-trivial (i.e., not 1) divisor of n by testing (via the division algo-
rithm) the possible divisors in order from smallest to largest. The smallest
non-trivial divisor must be prime; call it p1 .
n = 27489 = 3 · 7 · 7 · 11 · 17 = 3 · 72 · 11 · 17.
def smallestdivisor(n):
"""returns the smallest non-trivial divisor of n"""
d = 2 # to begin
while n % d != 0:
d = d+1
return d
def factors(n):
"""returns the prime factorization of n"""
if n == 1:
return [ ] # empty list
else:
p = smallestdivisor(n)
return [p] + factors(n/p)
1
Here’s an example of this code in action, again running in a command
shell, and assuming that the code has been saved into a text file named
factors.py:
$ python
>>> from factors import *
>>> factors(60003)
[3, 3, 59, 113]
>>> factors(1234567)
[127, 9721]
>>> factors(987654321)
[3, 3, 17, 17, 379721]
>>> factors(9721)
[9721]
>>> factors(1234567890123456789)
[3, 3, 101, 3541, 3607, 3803, 27961]
>>>
Warning: If the input n is a very large prime, then so many divisions need
to be performed that even a supercomputer will take an incredibly long time
to return an answer.
2
To carry out this method, given an odd n, search for perfect squares in the
sequence
u2 − n, (u + 1)2 − n, (u + 2)2 − n, . . .
√
where u is the smallest integer greater than n. Assuming that n is odd,
this will always work.
Fermat compiled lists of squares in order to apply the method, but with a
calculator or computer it is easy enough to see if a given number is a perfect
square.
Fermat’s method is faster than the naive method when n has two factors of
roughly the same number of digits, but it can be very slow in some cases.
The existence of Fermat’s method has implications for modern cryptography.
Here’s Python code that carries out Fermat factorization:
Assuming the code is saved in a file named fermatfactor.py you can run
it in a terminal, as follows:
3
$ python
>>> from fermatfactor import *
>>> fermatfactor(9991013)
(4093, 2441)
>>> fermatfactor(9991013191)
(221231, 45161)
>>> fermatfactor(99910131919153)
(51696809, 1932617)
The code will run the longest time if the input n is actually a prime. In the
case where n = pq is the product of two large primes of the same number
of digits, Fermat factorization should be considerably faster than the naive
method.
The final topic we consider is the distribution of primes. This is a topic that
has attracted the attention of many mathematicians over the years.
Definition. Let π(x) be the number of primes not exceeding x, for any
positive real number x.
π(x)
lim = 1.
x→∞ f (x)
x
Theorem (The Prime Number Theorem). The function f (x) = ln(x) is an
asymptotic approximation for π(x), in the sense that limx→∞ π(x)
f (x) = 1.
In the theorem, the function ln(x) is the natural logarithm function; i.e.,
the inverse of the natural exponential function exp(x) = ex where e =
n
2.718281828459045 . . . is Euler’s constant defined by e = limn→∞ 1 + n1 .
4
It is known that an even better estimate for π(x) is given by the function
Li(x) defined by the following integral:
Z x
dt
Li(x) = .
2 ln(t)
Note that “Li” stands for Logarithmic integral here. Methods of calculus
can be used to compute Li(x).
π(x)
Again, it has been shown that limx→∞ Li(x) = 1, so the function Li(x) is
another asymptotic approximation for π(x).
x
In fact, the function ln(x) provides an underestimate for π(x) while Li(x)
x
proves an overestimate. For example, with x = 1000 we get ln(x) = 144.8
and Li(x) = 178, so π(1000) is somewhere between 145 and 178. In fact,
π(1000) = 168.