Today I faced a problem: how to generate a pseudo-random permutation of numbers in range [0,2^128), such that each number appears
exactly once. An obvious solution is to initialize an array
A[i]=i
and then shuffle elements with repeated calls to
random()
. However, that would use a large amount of memory, which is not acceptable in this particular case.
So I remembered a bit of algebra that I learned long time ago at the university. It's about
cyclic groups. Consider the sequence
k*a0 % M
for k = 0, 1, .... In my case
M=2^128
. This sequence generates
all numbers less than
M
exactly once, provided that
a0
and
M
are relatively prime. Shortly,
a0
is a
generator of an additive cyclic group where the set of elements are natural numbers in the range
G=[0,2^128)
, and the operation is addition modulo
M
.
The code is even simpler (pseudo-C):
a = 0;
do {
/* use a in some way */
a += a0;
if(a > M) a -= M;
} while(a);
When
a
becomes 0 again, the whole group of
M
elements has been generated, so the loop exits. In other words,
a
has cycled through all elements in
G
exactly once. This is also connected with pseudo-random number generators. I'm not interested in the exact statistical properties of generated numbers; the only requirement is that consecutive numbers are "far enough" apart (which I define by chosing an appropriate constant
a0
).
Tags:
algebra random numbers