I would like some sort of method to create a fairly long sequence of random numbers that I can flip through backwards and forwards. Like a machine with "next" and "previous" buttons, that will give you random numbers.
Something like 10-bit resolution (i.e. positive integers in a range from 0 to 1023) is enough, and a sequence of >100k numbers. It's for a simple game-type app, I don't need encryption-strength randomness or anything, but I want it to feel fairly random. I have a limited amount of memory available though, so I can't just generate a chunk of random data and go through it. I need to get the numbers in "interactive time" - I can easily spend a few ms thinking about the next number, but not comfortably much more than that. Eventually it will run on some sort of microcontroller, probably just an Arduino.
I could do it with a simple linear congruential generator (LCG). Going forwards is simple, to go backwards I'd have to cache the most recent numbers and store some points at intervals so I can recreate the sequence from there.
But maybe there IS some pseudo-random generator that allows you to go both forwards and forwards? It should be possible to hook up two linear feedback shift registers (LFSRs) to roll in different directions, no?
Or maybe I can just get by with garbling the index number using a hash function of some sort? I'm going to try that first.
Any other ideas?
This is absolutely possible - you just have to create a PRNG which suits your purposes.
A sequence of pseudorandom numbers is generated by a deterministic algorithm and should simulate a sequence of independent and uniformly distributed random variables on the interval [0, 1]. In order to be acceptable, a sequence of pseudorandom numbers must pass a variety of statistical tests for randomness.
The DRBG produces a sequence of bits from a secret initial value called a seed. A cryptographic DRBG has the additional property that the output is unpredictable given that the seed is not known. A DRBG is sometimes also called a pseudo-random number generator (PRNG) or a deterministic random number generator.
PRNGs generate a sequence of numbers approximating the properties of random numbers. A PRNG starts from an arbitrary starting state using a seed state. Many numbers are generated in a short time and can also be reproduced later, if the starting point in the sequence is known.
I asked a very similar question at the tigsource forums.
At least in games, a hash function could probably do what you want. You could do it like this
class ReversibleRNG { int x; public: ReversibleRNG(int seed) : x(seed) {} int next(){return yourFavoriteHash(++x);} int prev(){return yourFavoriteHash(--x);} };
As multiple people have pointed out, an lcg is indeed reversible. In an lcg, the next state is computed like this:
x = (a * prevx + c) mod m
We can reorder this:
x ≡ a * prevx + c (mod m) x - c ≡ a * prevx (mod m)
Since a and m are chosen to be relatively prime in an lcg, we can find the inverse by using the extended euclid's algorithm.
ainverse = extEuclid(a, m).x; ainverse * (x - c) ≡ ainverse * a * prevx (mod m) ainverse * (x - c) ≡ prevx (mod m)
Which means
prevx = ainverse * (x - c) mod m
If you choose m and a carefully, the algorithm can have a period of 2^64
I did a header-only implementation of this algorithm in case anyone's interested.
Using a really simple symmetric encryption algorithm is one of the easiest ways to do this. Each random number is formed by just encrypt the previous one with some fixed key and to go backwards you just decrypt.
You might look at the RC4 - Code at http://en.wikipedia.org/wiki/RC4. You could use a much smaller key schedule to get it to all fit on an arduino.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With