# Random Number Generator Seeding Function - Java-Games

This is a discussion on Random Number Generator Seeding Function - Java-Games ; Ok, I know that srand( time(NULL) ) isn't such a good idea, but I do it anyway. Why? The clock is an easy source of randomness. And I've got this sneaky suspicion that I'm not the first guy to commit ...

1. ## Random Number Generator Seeding Function

Ok, I know that srand( time(NULL) ) isn't such a good idea, but I do it
anyway. Why? The clock is an easy source of randomness. And I've got this
sneaky suspicion that I'm not the first guy to commit this foul atrocity
against the finer design principles of RNGs in general...

So here's me thought: Design a seeding function that has only one purpose --
and that purpose is to use time(NULL) as it's input, and generate a
reasonably random output for seeding a random number generator.

As of right now, the value of time(NULL) on my machine is: 1095397643 (1.095
billion), and increments once per second. the return value is of time_t,
which according to www.cplusplus.com is generally defined as a long. It's
four bytes on my machine.

USAGE:
It occurs to me that this function doesn't really have to return a different
series ten thousand years from now. Most people are going to use it in rapid
succession several times over the course of an hour or three -- usually the
same hour or three in a day. Thus it should be out of synch with the daily
cycle of time, and after several days it doesn't matter if it cycles. Maybe
six days, so that it doesn't match a week.

6 days x 24 hours/day x 60 minutes/hour x 60 seconds/minute = 518,400
seconds; or about half a million descreet starting values. BTW, 2^19 =
524288; might be convenient. 32 bits - 19 bits = 13 bits.

So basically, what I'm looking at is doing something with time(NULL) >> 13.

QUESTION:
In what ways can we manipulate this small subset of numbers to provide a
random spread across the range [0..2^19] or so?

2. ## Re: Random Number Generator Seeding Function

In article <GLu2d.205331\$mD.123098@attbi_s02>,
no_spam_anglewyrm@hotmail.com says...
> Ok, I know that srand( time(NULL) ) isn't such a good idea, but I do it
> anyway. Why? The clock is an easy source of randomness. And I've got this
> sneaky suspicion that I'm not the first guy to commit this foul atrocity
> against the finer design principles of RNGs in general...
>
> So here's me thought: Design a seeding function that has only one purpose --
> and that purpose is to use time(NULL) as it's input, and generate a
> reasonably random output for seeding a random number generator.

Just call rand() a few times after seeding it with time( NULL ), and
after that you will get a decent spread.

You CAN get burned if you omit this.

If you can get at the seed, just grab that after a couple of calls. Or
else emulate the formulas typically used by rand().

However, rand() is good enough for most purposes. And I think you need
to think more about RNGs. If you want to use a better generator than
rand(), don't use rand() at all - seed your preferred RNG directly!

One option is to use a persistent value - i.e. store the current seed
between runs. Of course this won't work well if there are multiple
instances of the program...

- Gerry Quinn

3. ## Re: Random Number Generator Seeding Function

"Gerry Quinn" <gerryq@DELETETHISindigo.ie> wrote in message
news:MPG.1bb4c93cd7d622e698995a@news.indigo.ie...
> In article <GLu2d.205331\$mD.123098@attbi_s02>,
> no_spam_anglewyrm@hotmail.com says...
> > Ok, I know that srand( time(NULL) ) isn't such a good idea, but I do it
> > anyway. Why? The clock is an easy source of randomness. And I've got

this
> > sneaky suspicion that I'm not the first guy to commit this foul atrocity
> > against the finer design principles of RNGs in general...
> >
> > So here's me thought: Design a seeding function that has only one

purpose --
> > and that purpose is to use time(NULL) as it's input, and generate a
> > reasonably random output for seeding a random number generator.

>
> Just call rand() a few times after seeding it with time( NULL ), and
> after that you will get a decent spread.

Calling rand() once removes the sequential stepping after the seeding; this
might be the direction needed.

> If you can get at the seed, just grab that after a couple of calls.

The seed is the return value of rand().

> Or else emulate the formulas typically used by rand().
>
> However, rand() is good enough for most purposes. And I think you need
> to think more about RNGs. If you want to use a better generator than
> rand(), don't use rand() at all - seed your preferred RNG directly!
>
> One option is to use a persistent value - i.e. store the current seed
> between runs. Of course this won't work well if there are multiple
> instances of the program...

Actually, I've done quite a bit of thinking about random number generators:

////////////////////////////////////////////////////////////////////////////
////
// marginal improvement on std::rand()
// This functor stores state information,
// so that multiple instances can have different seeds.
// NOTE: This class is not thread safe; if multiple threads poll rand(),
// then the sequence of numbers from a given seed won't be repeatable.
class rng_class {
public:
void seed( unsigned int s ){ current = s; };
unsigned int operator()(unsigned int range)
{
if ( range == 0 ) return 0; // only one possibility.

// save global rand state, and restore this instance's state
unsigned int global_state = rand();
srand( current );

// handle cases where range doesn't evenly divide RAND_MAX,
unsigned int bucket_size = RAND_MAX / range;
unsigned int result;
do {
current = std::rand();
result = current / bucket_size;
} while ( result >= range );

srand( global_state ); // restore global state

return result;
}
protected:
unsigned int current;
};

4. ## Re: Random Number Generator Seeding Function

In article <lbD2d.65350\$D%.46702@attbi_s51>,
no_spam_anglewyrm@hotmail.com says...
> "Gerry Quinn" <gerryq@DELETETHISindigo.ie> wrote in message
> news:MPG.1bb4c93cd7d622e698995a@news.indigo.ie...

> > If you can get at the seed, just grab that after a couple of calls.

> The seed is the return value of rand().

Not unless the implementation of rand() is quite disastrous! In MSVC I
think it is bits 8 - 22, and this is probably typical.

- Gerry Quinn

5. ## Re: Random Number Generator Seeding Function

"Gerry Quinn" <gerryq@DELETETHISindigo.ie> wrote in message
news:MPG.1bb51b5d587643f1989965@news.indigo.ie...
> In article <lbD2d.65350\$D%.46702@attbi_s51>,
> no_spam_anglewyrm@hotmail.com says...
> > "Gerry Quinn" <gerryq@DELETETHISindigo.ie> wrote in message
> > news:MPG.1bb4c93cd7d622e698995a@news.indigo.ie...

>
> > > If you can get at the seed, just grab that after a couple of calls.

>
> > The seed is the return value of rand().

>
> Not unless the implementation of rand() is quite disastrous! In MSVC I
> think it is bits 8 - 22, and this is probably typical.
>

The formula for Linear Congruential RNGs as I understand it is:

value[i+1] = coefficient * value[i] + constant (mod modulus)

where coefficient, constant, and modulus are carefully chosen.

6. ## Re: Random Number Generator Seeding Function

"AngleWyrm" <no_spam_anglewyrm@hotmail.com> wrote in message
news:ylE2d.208738\$Fg5.188045@attbi_s53...
> "Gerry Quinn" <gerryq@DELETETHISindigo.ie> wrote in message
> news:MPG.1bb51b5d587643f1989965@news.indigo.ie...
> >
> > > > If you can get at the seed, just grab that after a couple of calls.
> > > The seed is the return value of rand().

> > Not unless the implementation of rand() is quite disastrous! In MSVC I
> > think it is bits 8 - 22, and this is probably typical.

>
> The formula for Linear Congruential RNGs as I understand it is:
> value[i+1] = coefficient * value[i] + constant (mod modulus)
> where coefficient, constant, and modulus are carefully chosen.

There is still something missing here. I've done a test run (see below) to
compare rand() vs rand() seeded with it's return value. First nine outputs
for rand and srand(rand), both started with srand(1):

// Test Run /////////////////////////////
41 18467 6334 26500 19169 15724 11478 29358 26962
41 172 600 1997 6559 21457 4572 14968 16149

Evidently rand() does not directly use it's return value.

7. ## Re: Random Number Generator Seeding Function

On Fri, 17 Sep 2004 05:38:47 GMT, "AngleWyrm"
<no_spam_anglewyrm@hotmail.com>:

>Most people are going to use it in rapid
>succession several times over the course of an hour or three -- usually the
>same hour or three in a day.

Allow me to butt in...

If you want to make sure that one person will never get twice the same
random number sequence, it's rather simple: just make sure this person
doesn't call srand() more than once per second. For example, make sure
that srand() is only called once in your program -- calling it several
times is a waste of resources and a call for problems.

If you want to make sure that two people in the world, using your
program, don't get the same random number sequence, you'll have to add
another information, unique for each user. For example, a license
number, or the date of creation of the directory your program is in
(i.e. the date and time the user installed your program), or the
number of bytes left on the hard disk, etc.

Two additional notes:
- a good random number generator always generate two very
different random number sequences when given two different seeds --
even if the seeds are one bit apart.
- the rand() function provided with the C and C++ standard
library is usually quite bad. Even PHP has a better generation,
mt_rand(). For C++, you might want to try
<http://www.gabi-soft.fr/code/Util/Basic/Random/>, which seems to be
an implementation of a better algorithm, and maybe faster than a call
to rand().

--
;-)

8. ## Re: Random Number Generator Seeding Function

In article <PDL2d.108104\$3l3.94590@attbi_s03>,
no_spam_anglewyrm@hotmail.com says...
> "AngleWyrm" <no_spam_anglewyrm@hotmail.com> wrote in message
> news:ylE2d.208738\$Fg5.188045@attbi_s53...

> > The formula for Linear Congruential RNGs as I understand it is:
> > value[i+1] = coefficient * value[i] + constant (mod modulus)
> > where coefficient, constant, and modulus are carefully chosen.

>
> There is still something missing here. I've done a test run (see below) to
> compare rand() vs rand() seeded with it's return value. First nine outputs
> for rand and srand(rand), both started with srand(1):
>
> // Test Run /////////////////////////////
> 41 18467 6334 26500 19169 15724 11478 29358 26962
> 41 172 600 1997 6559 21457 4572 14968 16149
>
> Evidently rand() does not directly use it's return value.

I'm sure I've seen the formula somewhere (in fact you could probably
deduce it from the series). But anyway it is an LCG with a 32-bit seed
and it only returns 15 of the middle bits.

- Gerry Quinn

9. ## Re: Random Number Generator Seeding Function

In article <l37nk0ddqoij0csfiq60jco2ujba0577d6@4ax.com>,
gramster@gramster.com says...

> Two additional notes:
> - a good random number generator always generate two very
> different random number sequences when given two different seeds --
> even if the seeds are one bit apart.

You can fix this issue by calling rand() a couple times and discarding
the results after every call to srand().

> - the rand() function provided with the C and C++ standard
> library is usually quite bad. Even PHP has a better generation,
> mt_rand(). For C++, you might want to try
> <http://www.gabi-soft.fr/code/Util/Basic/Random/>, which seems to be
> an implementation of a better algorithm, and maybe faster than a call
> to rand().

For serious use, you need a better RNG than rand(), though rand() will
suffice for most games. There are plenty of alternatives on the net.

- Gerry Quinn

10. ## Re: Random Number Generator Seeding Function

AngleWyrm wrote:
> Ok, I know that srand( time(NULL) ) isn't such a good idea, but I do it
> anyway. Why? The clock is an easy source of randomness. And I've got this
> sneaky suspicion that I'm not the first guy to commit this foul atrocity
> against the finer design principles of RNGs in general...
>
> So here's me thought: Design a seeding function that has only one purpose --
> and that purpose is to use time(NULL) as it's input, and generate a
> reasonably random output for seeding a random number generator.
>
> As of right now, the value of time(NULL) on my machine is: 1095397643 (1.095
> billion), and increments once per second. the return value is of time_t,
> which according to www.cplusplus.com is generally defined as a long. It's
> four bytes on my machine.

srand(time(NULL)); is generally fine for producing random numbers.
(mix in the getpid() as well if you're on *nix)
It's just that knowing the time(roughly) and the algorithm used, one can
predict/calculate the random number. This is very bad if you use it
for crypto algorithms. Mostly fine otherwise.

One thing one can do is to write out the next random number to a file
when the program ends, and use that as a seed the next time it starts..