3

In Linux. There is an srand() function, where you supply a seed and it will guarantee the same sequence of pseudorandom numbers in subsequent calls to the random() function afterwards.

Lets say, I want to store this pseudo random sequence by remembering this seed value.

Furthermore, let's say I want the 100 thousandth number in this pseudo random sequence later.

One way, would be to supply the seed number using srand(), and then calling random() 100 thousand times, and remembering this number.

Is there a better way of skipping all 99,999 other numbers in the pseudo random list and directly getting the 100 thousandth number in the list.

thanks,

m

4
  • Note that srand seeds rand, and srandom seeds random. Commented May 4, 2010 at 22:15
  • I'd be interesting in knowing the use case behind this - I think I'm missing something, as I can't see why the 100,000th sequence is more random than the first. Commented Feb 22, 2011 at 4:37
  • @HorusKol It's been a while, but ending up here via google when interested in something related, I do feel like giving you a use case. Imagine a game that gives you a series of puzzles, each generated from a single number. To make sure that each person gets different puzzles, you use a random generator and you remember the initial seed. Now, you may want the user be able to continue where he left (at which time the seed is known, which makes things easier) or even to replay any puzzle as long as he remembers its number. Commented Jul 27, 2012 at 23:28
  • (Yes, I had to stretch it a little to get a complete use case. However, the idea is that it isn't about "more random" but about "recreating" something "random" (thus actually turning the pseudo-part of the randomness into an advantage) Commented Jul 27, 2012 at 23:31

4 Answers 4

2

I'm not sure there's a defined standard for implementing rand on any platform; however, picking this one from the GNU Scientific Library:

— Generator: gsl_rng_rand

This is the BSD rand generator. Its sequence is

xn+1 = (a xn + c) mod m

with a = 1103515245, c = 12345 and m = 231. The seed specifies the initial value, x1. The period of this generator is 231, and it uses 1 word of storage per generator.

So to "know" xn requires you to know xn-1. Unless there's some obvious pattern I'm missing, you can't jump to a value without computing all the values before it. (But that's not necessarily the case for every rand implementation.)

If we start with x1...

  • x2 = (a * x1 + c) % m
  • x3 = (a * ((a * x1 + c) % m) + c) % m
  • x4 = (a * ((a * ((a * x1 + c) % m) + c) % m) + c) % m
  • x5 = (a * (a * ((a * ((a * x1 + c) % m) + c) % m) + c) % m) + c) % m

It gets out of hand pretty quickly. Is that function easily reducible? I don't think it is.

(There's a statistics phrase for a series where xn depends on xn-1 -- can anyone remind me what that word is?)

Sign up to request clarification or add additional context in comments.

3 Comments

RE: statistics phrase. Markov chain of order 1? Though not really in this case, since x_n isn't independent of x_(n-2).
This isn't a Markov chain. It's basically just a recurrence relation over the integers modulo 2^31.
BTW That recurrence relation is pretty easy to solve. Remember you can pull all of those % m operations out to a single application of % m at the end. The resulting relation is a textbook example. But turning it into an efficient and usable piece of code takes a bit more work because applying it naively requires arbitrary precision integers. But I think there may be a way to get that partly under control.
1

If they're available on your system, you can use rand_r instead of rand & srand, or use initstate and setstate with random. rand_r takes an unsigned * as an argument, where it stores its state. After calling rand_r numerous times, save the value of this unsigned integer and use it as the starting value the next time.

For random(), use initstate rather than srandom. Save the contents of the state buffer for any state that you want to restore. To restore a state, fill a buffer with and call setstate. If a buffer is already the current state buffer, you can skip the call to setstate.

Comments

1

This is developed from @Mark's answer using the BSD rand() function.

rand1() computes the nth random number, starting at seed, by stepping through n times.

rand2() computes the same using a shortcut. It can step up to 2^24-1 steps in one go. Internally it requires only 24 steps.

If the BSD random number generator is good enough for you then this will suffice:

#include <stdio.h> const unsigned int m = (1<<31)-1; unsigned int a[24] = { 1103515245, 1117952617, 1845919505, 1339940641, 1601471041, 187569281 , 1979738369, 387043841 , 1046979585, 1574914049, 1073647617, 285024257 , 1710899201, 1542750209, 2011758593, 1876033537, 1604583425, 1061683201, 2123366401, 2099249153, 2051014657, 1954545665, 1761607681, 1375731713 }; unsigned int b[24] = { 12345, 1406932606, 1449466924, 1293799192, 1695770928, 1680572000, 422948032, 910563712, 519516928, 530212352, 98880512, 646551552, 940781568, 472276992, 1749860352, 278495232, 556990464, 1113980928, 80478208, 160956416, 321912832, 643825664, 1287651328, 427819008 }; unsigned int rand1(unsigned int seed, unsigned int n) { int i; for (i = 0; i<n; ++i) { seed = (1103515245U*seed+12345U) & m; } return seed; } unsigned int rand2(unsigned int seed, unsigned int n) { int i; for (i = 0; i<24; ++i) { if (n & (1<<i)) { seed = (a[i]*seed+b[i]) & m; } } return seed; } int main() { printf("%u\n", rand1 (10101, 100000)); printf("%u\n", rand2 (10101, 100000)); } 

It's not hard to adapt to any linear congruential generator. I computed the tables in a language with a proper integer type (Haskell), but I could have computed them another way in C using only a few lines more code.

Comments

0

If you always want the 100,000th item, just store it for later.

Or you could gen the sequence and store that... and query for the particular element by index later.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.