
Prime Clockwork – A Simple Automaton to Generate Natural Numbers and Their Prime Factors
15.8.2024, by Michael Emmerich
1. What is the prime clockwork?
This work presents the prime clockwork, an automaton that generates all natural numbers in prime factorization starting from one, using only integer addition and comparison -— no division or multiplication. The prime clockwork is an array of independent prime clocks that generate number sequences and discover prime numbers organically without prior knowledge. The rationale behind this method lies in its potential to shed some light on the intrinsic nature of integers and prime numbers.
While the lemmas are provable with basic number theory and we do not claim they are completely new, we belief the prime clockwork might present a new way to view the natural numbers and compute their prime factorizations. We are inspired by the rich body of past work on this topic area, especially on prime factorization. Recognizing the rich history of prime studies from Euclid to Euler, we may have missed some references and invite reader comments on any important related work.
2. Prime Vector Basics
Prime vectors are basic data structures to represent numbers in a positional notation (see, for instance, \url{https://emmerix.net/2024/07/29/playing-with-primes}). They are based on the fundamental theorem of number theory that states that each natural number can be stated as a prime vector.
Definition 1 For, represent
as
, where
are primes and
. We define a prime vector as an infinite list
. The mapping between integers and prime vectors is
, with the inverse
. The space of prime vectors is
.
Lemma 2 Prime vectors uniquely represent all natural numbers, establishing a one-to-one correspondence betweenand
.
Proof: This follows from the fundamental theorem of arithmetic, which states every integer has a unique prime factorization.
Definition 3 Define theoperator on
as
.
Lemma 4 Forand
with
,
.
Proof: Since and
denote the non-zero exponents of prime factors of
and
, respectively, we have
.
Prime vectors enable elegant computation of number properties, such as:
Lemma 5 Letand
. The Greatest Common Divisor
is given by
The Least Common Multiple
is given by
Let us also consider the smallest prime vector representing 1.
Lemma 6 For,
. That is,
corresponds to the natural number
.
To keep things concise, this discussion will focus only on addition and multiplication defined in natural numbers, and the smallest number taken into account is .
3. Prime Clockwork
We will show that counting natural numbers as prime vectors can be described by a ‘clockwork’ of autonomous ‘clocks’, each linked to a unique prime number and producing prime vector digits independently. Coupling occurs only when all clocks show zero, triggering the birth of a new prime number and a new clock. We first assume primes are known and will later discuss their on-the-fly generation.
Definition 7 A prime clock for prime, denoted
, is a recursive automaton starting at
and generating an output
each iteration. It has a seconds counter that
that is increased by one in each iteration, and reset to
before it reaches
, i.e. it holds
. It has a minutes counter
that starts with
and increases by one after each reset of the seconds counter. The prime clock outputs
whenever
, and
otherwise.
Remark 1 Using a clock metaphor, letbe the total seconds passed and
the minutes.
is the seconds hand which is reset to 0 when it finished a full round. Each minute has
seconds on the clock
. Unlike real clocks, seconds and minutes are not displayed and there is no cap on minutes.
Lemma 8 The prime clockgenerates as output
the
-th digit of the prime vector
during the
-th iteration.
Proof: The output is zero if
, i.e.,
is not divisible by
. If
, then
. In prime vector notation,
. By Lemma 4, compute the
-th digit of
with
.
The recursive definition below implements the prime clockwork without needing the modulo operator:
Definition 9 We operate autonomous prime clocks for each prime. For each iteration
, the prime clocks output a digit
such that
, representing the exponents in the prime factorization of
. Let
and
be the states of the clock
, where
is the step (second pointer) and
is the number of complete cycles (minute pointer).
The next step function is defined recursively as follows:
Remark 2 The prime clocks have three key properties:
- Autonomy: Each prime clock
operates independently, without the need to know the states of other clocks. The clockwork array generates the prime vectors sequentially in ascending order.
- Efficiency: Prime clocks use only a few constant integer additions and comparisons, and they operate without multiplication, division, and modulo computations.
- Periodicity: Prime clocks output non-zero in exactly every
th iteration starting when
. In particular, a prime factor is blocked for
iterations after it has been used and then will be part of the prime factorization again.
One might argue that this mechanism needs infinite clocks and prior knowledge of the prime number. However, clocks can be added “on the fly” when zero digits appear in all outputs.
Definition 10 {Dynamic Prime Clockwork} Let us assume that we start the counting process with only one active prime clock in the array, the prime clock for. Let
be active prime clocks starting from
that output
simultaneously for the first time, that is,
for all
. In this case
is prime, and a new prime clock
is activated and added with
. It is initialized by running it from
to
. Then the prime vector we output at
is
and
.
Lemma 11 The dynamic prime clockwork produces all prime vectors of integers one by one and adds prime clocks as soon as they are needed, that is, they produce non-zero output.
Proof: The crucial observation here is that is prime, and this is concluded from the fact that
and the uniqueness of the prime factorization. Since
cannot be divided by any of the numbers
, and certainly not by a number greater than
,
must be prime.
This dynamic clockwork has been implemented in Python; we include source code and example output for the first 30 natural numbers in the Appendix.
Remark 3 At a given time, most prime clocks output zero, suggesting a high frequency of prime numbers for small numbers of active prime clocks. Over time, the newly added prime clocks have a decreased frequency of output non-zero values, but it still becomes harder for a new prime number to occur, as more clocks need to simultaneously show zero.
In summary, the prime clockwork efficiently generates natural numbers by their prime factorization using integer addition and comparison only. It requires no prior knowledge of primes, with the successor computation being efficient and constant in operations that are restricted to integer addition and comparison. Prime numbers and their clocks are generated on the fly as needed.
4. Addition and Multiplication
The prime clockwork operates clocks independently if it is provided with the primes. Thus, we can define addition and multiplication at the level of a single clock . This can be done as follows.
The prime clockwork operates clocks independently if it is provided with the primes. Thus, we can define addition and multiplication at the level of a single clock . This can be done as follows.
Definition 12 {Addition} For two prime clock statesin
and
in
, the addition
is defined as follows:
Definition 13 {Multiplication} For two prime clock statesin
and
in
, the multiplication
is defined as follows:
Remark 4 This update maintains, as expected, the property that the prime clocks can be run as independent processes.This reveals that multiplication is memoryless when used alone. However, for addition, we need the seconds pointer, minutes pointer, new prime numbers, and preceding clock states to perform it efficiently. Alternatively, we can resort to a step-by-step simulation from
- To know the output of multiplication, it is sufficient to know the output of the clocks
and
in
and
. This is consistent with Lemma 4. An interesting observation is that the prime numbers are already represented with non-zero values in either one of the two factors. That is, multiplication never adds new prime factors, but only combines the prime factors of the two input integers.
- To implement the addition, we also require the current position of the second counter
and the minute counter
, as well as the history outputs of the prime clock prior to the two summation factors. In principle, these values can be recomputed with some computational effort using the information stored in the prime vectors
and
. Moreover addition operations on the level of the clockwork might require the activation of additional prime clocks in the dynamic clockwork, as additional prime numbers might be needed to represent the result.
- Multiplication may affect the values of
and
. Thus, if addition is applied to the result of multiplication,
and
need to be updated also in multiplication.
- If we are only interested in whether or not
, that is, whether or not
divides
, neither the minute counters
, nor the history of past outputs are needed. Thus, there is hope that some questions regarding the integers and prime numbers can be answered using a simpler, binary, representation of numbers.
or any time when the clock state was known, using only the information stored in the prime vectors for addition. Here, restoring the information of
and
can be accomplished by dividing the whole by the remainder using
, but to acquire the knowledge of all
that are relevant in representing the result of the addition might be difficult to accomplish without a step-by-step simulation of the dynamic prime clockwork. However, this could be computationally inefficient.
Sometimes we can, however, easily conclude the result of addition even if there is incomplete information on the prime clocks’ internal states. The following lemma specifies the prime factors in the sum of two prime vectors.
Lemma 12 Letand
denote two vectors and
. Then
Proof: The lemma follows from the clockwork mechanism. When , the seconds pointer of the prime clock for
hits zero. Therefore, only if
do we add whole minutes to the seconds, as in the lemma 16; otherwise, the non-zero position seconds pointer results in a zero output as in equation 15. We used the fact that all prime clocks run independently.
Remark 5 Only in case, the output can be anything
or
. In all other cases the output of the addition of two prime clocks is well defined by the information provided with
and
, without requiring knowledge of the seconds and minutes and past outputs.
5. Python Implementation of the Prime Clockwork
Here is a Python source code for the Prime Clockwork simulation. Prime clocks operate autonomously and are unaware of each other’s outputs. Adding a prime clock occurs upon the birth of a new prime number, which requires the observation that all active prime clocks are in state . We use no precomputed primes.
class PrimeClock:
def __init__(self, prime):
self.prime = prime
self.s = 0
self.m = 0
self.outputs = [0] # positive_outputs
def next(self):
self.s += 1
if self.s == self.prime:
self.s = 0
self.m += 1
if self.s == 0:
output = 1 + self.outputs[self.m]
else:
output = 0
self.outputs.append(output)
return output
class Clockwork:
def __init__(self):
self.t = 0
self.clocks = []
for prime in [2, 3]:
self.clocks.append(PrimeClock(prime))
def next(self):
digits = [clock.next() for clock in self.clocks]
self.t += 1
return digits, self.t
def add_new_clock(self):
new_prime = self.t
new_clock = PrimeClock(new_prime)
for _ in range(self.t):
new_clock.next()
self.clocks.append(new_clock)
return new_clock.outputs[-1]
def run(self, max_iterations):
for _ in range(max_iterations):
digits, t = self.next()
if all(d == 0 for d in digits) and t > 2:
new_output = self.add_new_clock()
digits.append(new_output)
print(f"{t}\t" + "\t".join(map(str, digits)))
if __name__ == "__main__":
max_iterations = 30
clockwork = Clockwork()
clockwork.run(max_iterations)
It produces the following output:
| Time | P2 | P3 | P5 | P7 | P11 | P13 | P17 | P19 | P23 | P29 |
| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 3 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 4 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 5 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 6 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 7 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| 8 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 9 | 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 10 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 11 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| 12 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 13 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
| 14 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| 15 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 16 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 17 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
| 18 | 1 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 19 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
| 20 | 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 21 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| 22 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| 23 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
| 24 | 3 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 25 | 0 | 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 26 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
| 27 | 0 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 28 | 2 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| 29 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| 30 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Acknowledgements: I gratefully acknowledge contributions in discussions and feedback provided by Mutlu Özdemir from Dortmund, Germany on the ideas presented in this essay.
Michael Emmerich: Playing with primes, pubished online July 29th, 2024.
One response to “Prime Clockwork”
[…] Michael T. M. Emmerich, “Prime Clockwork,” emmerix.net. […]