1

Possible Duplicate:
Why do I always get the same sequence of random numbers with rand()?

I've been experimenting with generating random numbers in C, and I've come across something weird. I don't know if it's only on my compiler but whenever I try to generate a pseudo-random number with the rand() function, it returns a very predictable number — the number generated with the parameter before plus 3.125 to be exact. It's hard to explain but here's an example.

srand(71);
int number = rand();
printf("%d", number);

This returns 270.

srand(72);
int number = rand();
printf("%d", number);

This returns 273.

srand(73);
int number = rand();
printf("%d", number);

This returns 277.

srand(74);
int number = rand();
printf("%d", number);

This returns 280.

Every eighth number is 4 higher. Otherwise it's 3.

This can't possibly be right. Is there something wrong with my compiler?

Edit: I figured it out — I created a function where I seed only once, then I loop the rand() and it generates random numbers. Thank you all!

Community
  • 1
  • 1

4 Answers4

3

The confusion here is about how pseudorandom number generators work.

Pseudorandom number generators like C's rand work by having a number representing the current 'state'. Every time the rand function is called, some deterministic computations are done on the 'state' number to produce the next 'state' number. Thus, if the generator is given the same input (the same 'state'), it will produce the same output.

So, when you seed the generator with srand(74), it will always generate the same string of numbers, every time. When you seed the generator with srand(75), it will generate a different string of numbers, etc.

The common way to ensure different output each time is to always provide a different seed, usually done by seeding the generator with the current time in seconds/milliseconds, e.g. srand(time(NULL)).

EDIT: Here is a Python session demonstrating this behavior. It is entirely expected.

>>> import random

If we seed the generator with the same number, it will always output the same sequence:

>>> random.seed(500)
>>> [random.randint(0, 100) for _ in xrange(20)]
[80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]
>>> random.seed(500)
>>> [random.randint(0, 100) for _ in xrange(20)]
[80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]
>>> random.seed(500)
>>> [random.randint(0, 100) for _ in xrange(20)]
[80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]

If we give it a different seed, even a slightly different one, the numbers will be totally different from the old seed, yet still the same if the same (new) seed is used:

>>> random.seed(501)
>>> [random.randint(0, 100) for _ in xrange(20)]
[64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]
>>> random.seed(501)
>>> [random.randint(0, 100) for _ in xrange(20)]
[64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]
>>> random.seed(501)
>>> [random.randint(0, 100) for _ in xrange(20)]
[64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]

How do we make our program have different behavior each time? If we supply the same seed, it will always behave the same. We can use the time.time() function, which will yield a different number each time we call it:

>>> import time
>>> time.time()
1347917648.783
>>> time.time()
1347917649.734
>>> time.time()
1347917650.835

So if we keep re-seeding it with a call to time.time(), we will get a different sequence of numbers each time, because the seed is different each time:

>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[60, 75, 60, 26, 19, 70, 12, 87, 58, 2, 79, 74, 1, 79, 4, 39, 62, 20, 28, 19]
>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[98, 45, 85, 1, 67, 25, 30, 88, 17, 93, 44, 17, 94, 23, 98, 32, 35, 90, 56, 35]
>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[44, 17, 10, 98, 18, 6, 17, 15, 60, 83, 73, 67, 18, 2, 40, 76, 71, 63, 92, 5]

Of course, even better than constantly re-seeding it is to seed it once and keep going from there:

>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[94, 80, 63, 66, 31, 94, 74, 15, 20, 29, 76, 90, 50, 84, 43, 79, 50, 18, 58, 15]
>>> [random.randint(0, 100) for _ in xrange(20)]
[30, 53, 75, 19, 35, 11, 73, 88, 3, 67, 55, 43, 37, 91, 66, 0, 9, 4, 41, 49]
>>> [random.randint(0, 100) for _ in xrange(20)]
[69, 7, 25, 68, 39, 57, 72, 51, 33, 93, 81, 89, 44, 61, 78, 77, 43, 10, 33, 8]
Claudiu
  • 224,032
  • 165
  • 485
  • 680
0

Every invocation of rand() returns the next number in a predefined sequence where the starting number is the seed supplied to srand(). That' why it's called a pseudo-random number generator, and not a random number generator.

ninjalj
  • 42,493
  • 9
  • 106
  • 148
0

rand() is implemented by a pseudo random number generator.

The distribution of numbers generated by consecutive calls to rand() have the properties of being random numbers, but the order is pre-determined. The 'start' number is determined by the seed that you provide.

You should give a PRNG a single seed only. Providing it with multiple seeds can radically alter the randomness of the generator. In addition, providing it the same seed over and over removes all randomness.

Dancrumb
  • 26,597
  • 10
  • 74
  • 130
  • You have misunderstood, the four code snips above are not part of the same code file. – user1676037 Sep 17 '12 at 20:53
  • Actually, I did understand that; however, the point is that you should not expect to see random behavior if you call seed and then rand and do it multiple times. You will only observe random behaviour if you call rand multiple times after calling seed. – Dancrumb Sep 17 '12 at 20:58
0

Generating a "random" number regardless of the implementation is dependent on a divergent infinite sequence. The infinite sequence is generated using the seed of the random function and it is actually pseudo random because of its nature. This would explain to you why your number is actually very dependent on the seed that you give the function.

In some implementations the sequence is only one and the seed is the starting member of the sequence. In others there are difference sequences depending on the seed. If a seed is not provided then the seed is determined by the internal "clock".

The number is truncated when using an upper and lower bounds for your random number by respectively doing randValue % upperBound and randValue + lowerBound. Random implementation is very similar to Hash Functions. Depending on architecture the upper bound of the random value is set depending on what it the largest integer/double that it can carry out if not set lower by the user.

Konstantin Dinev
  • 34,219
  • 14
  • 75
  • 100