srand(time(0))

I

Ioannis Vranos

Is srand(time(0)); an effective solution for seeding rand(), or is there
any better approach?
 
V

Victor Bazarov

Ioannis said:
Is srand(time(0)); an effective solution for seeding rand(), or is
there any better approach?

Unless you're doing it too often (which might just lead to the same
seed passed to 'srand'), it's commonly accepted, provided that you
actually cast the result of 'time(0)' to unsigned (for portability's
sake):

srand(unsigned(time(0)));

V
 
I

Ioannis Vranos

Victor said:
Unless you're doing it too often (which might just lead to the same
seed passed to 'srand'), it's commonly accepted, provided that you
actually cast the result of 'time(0)' to unsigned (for portability's
sake):

srand(unsigned(time(0)));


Since the function prototype is

void srand(unsigned int seed);


doesn't an implicit conversion to unsigned int take place?
 
V

Victor Bazarov

Ioannis said:
Since the function prototype is

void srand(unsigned int seed);


doesn't an implicit conversion to unsigned int take place?

Uh... I am not sure. Probably. For some reason since the first
time I used it I've been convinced that the conversion is needed.
I may have been wrong all those years... If it works for you,
drop the conversion.

V
 
H

Hans Mull

Ioannis said:
Is srand(time(0)); an effective solution for seeding rand(), or is there
any better approach?
There are 3 functions which are better I think:
1.gettimeofday(): More precision (microsecond clock)
2.There is a function that countts the time since the system is running,
but I don't know what's it's name, just google for it
3. Timestep counter: called by ASM function readtsc, e.g. use that
inline asm function (GCC):


inline volatile unsigned long ReadTSC()
{
unsigned long tsc;
asm("rdtsc":"=A"(tsc));
return tsc;
}


The amount of timesteps (TS) per second is the reciprocal of the clock
frequency. Kind regards, Hans
 
M

Matthias Buelow

Hans said:
There are 3 functions which are better I think:
1.gettimeofday(): More precision (microsecond clock)
2.There is a function that countts the time since the system is running,
but I don't know what's it's name, just google for it
time()?

3. Timestep counter: called by ASM function readtsc, e.g. use that
inline asm function (GCC):
[...]

Of course it has to be said that neither 1. nor 3. is portable (unlike
the original solution.)
 
V

Victor Bazarov

Ioannis said:
I am afraid he means clock(), and its use for seeding srand() is worse
than time(0).

Neither. I believe Unix has something like "system uptime" you
could get, and Windows probably has something similar. But I
wouldn't use those.

V
 
E

Erik Wikström

Neither. I believe Unix has something like "system uptime" you
could get, and Windows probably has something similar. But I
wouldn't use those.

While I'm not an expert on the subject I do not think that the source of
the seed is very important as long as it is has a high probability of
not being identical on multiple invocations. The reason is that rand()
is (usually) not a very good PSNG so it should only be used in places
where good random number are required anyway.
 
V

Victor Bazarov

Erik said:
While I'm not an expert on the subject I do not think that the source
of the seed is very important as long as it is has a high probability
of not being identical on multiple invocations. The reason is that
rand() is (usually) not a very good PSNG

What does 'S' stand for in PSNG? Thanks.
so it should only be used in
places where good random number are required anyway.

V
 
E

Erik Wikström

What does 'S' stand for in PSNG? Thanks.

Opps, should be an 'R', as in Pseudo Random Number Generator. And with
'usually' I mean that while there is nothing (to my knowledge) that
prevents rand() from using an algorithm that produces good random
numbers most implementations do not. Which is probably one of the
reasons for the new PRNGs in the next version of the standard.
 
J

John Brawley

"Victor Bazarov"
Neither. I believe Unix has something like "system uptime" you
could get, and Windows probably has something similar. But I
wouldn't use those.

On a system where RAND_MAX is 32,767, this means there are only 32767 unique
numbers available in the first place, and srand(WhicheverIsUsed) merely
rearranges the order of the numbers 0 to 32767.

If one wanted more than 32767 numbers (say, for randomly-populating 100,000
xyz coordinates), then regardless of how often one rearranged them by
re-seeding the PRNG, how would one do that? Would it mean having to select
a non-integrated (to C++, for example) PRNG, thus risking non-portability?
 
V

Victor Bazarov

John said:
"Victor Bazarov"

On a system where RAND_MAX is 32,767, this means there are only 32767
unique numbers available in the first place, and
srand(WhicheverIsUsed) merely rearranges the order of the numbers 0
to 32767.

No, that's not correct. The numbers are not guaranteed to be unique
during picking RAND_MAX numbers. Some will repeat, some will not
come up.
If one wanted more than 32767 numbers (say, for randomly-populating
100,000 xyz coordinates), then regardless of how often one rearranged
them by re-seeding the PRNG, how would one do that?

There is no need to reseed the generator. The sequence can be good
enough for picking out of many more (that's controlled by the
generator's "period" characteristic and needn't be linked to the
RAND_MAX value at all. Even if you run into a shorter period PRNG,
you can always generate several sequences and then interleave them
with each other to get a relatively random final set.
Would it mean
having to select a non-integrated (to C++, for example) PRNG, thus
risking non-portability?

There are many good PRNGs on the 'net, pick one that suits your
needs, but first you need to prove that the built-in is not going
to suit you. There is no indicator to that yet, AFAICT (aside from
your doubt in its capabilities).

V
 
T

Triple-DES

No, that's not correct.  The numbers are not guaranteed to be unique
during picking RAND_MAX numbers.  Some will repeat, some will not
come up.

Yes, that's not how srand/rand normally works.

On many popular implementations the period is 2**32, but rand()
returns the state shifted right, ANDed with RAND_MAX to avoid the low-
order bits because they are not uniformly distributed in a typical
linear congruential generator. Thus RAND_MAX does not tell anything
about the period of the RNG.

Note that a conforming implementation could use a maximal period LCG
with a modulus of RAND_MAX, in which case John Brawleys description
would be mostly correct
There is no need to reseed the generator.  The sequence can be good
enough for picking out of many more (that's controlled by the
generator's "period" characteristic and needn't be linked to the
RAND_MAX value at all.  Even if you run into a shorter period PRNG,
you can always generate several sequences and then interleave them
with each other to get a relatively random final set.

What if you want to reproduce the sequence of numbers on a different
platform? If you use rand(), you can't do that. In this case using a
good PRNG written in ISO C++ (or C) is a better alternative.

DP
 
J

James Kanze

I am afraid he means clock(), and its use for seeding srand()
is worse than time(0).

He said since the system was running, not since the program was
running. (In fact, on the systems I regularly use, the first
call to clock() in a given process will always return 0. Not
very random as random seeds go.)

Of course, if you're not worried about portability:

std::ifstream src( "/dev/random", std::ios::binary ) ;
unsigned s ;
src.read( reinterpret_cast< char* >( &s ), sizeof( s ) ) ;
srand( s ) ;

(but with added error handling) is about as good as you can get.
In fact, what I generally use is something like:


std::ifstream src( "/dev/random", std::ios::binary ) ;
unsigned s ;
if ( ! src.read( reinterpret_cast< char* >( &s ), sizeof( s) ) ) {
s = time( NULL ) ;
}
srand( s ) ;

Alternatively (depending on the application), I might try mixing
in some other more or less random sources: the pid, the
machine's IP address, etc. But generally speaking, it's not
worth the bother. (Especially for srand/rand. If you're using
a known good generator, it might be worthwhile.)

A lot depends on why you want the random numbers. If you're
using them to seed the generator for backing off in case of
collision on a LAN, for example, time() is probably not a very
good source; if all of the machines are powered on at the same
time (quite possible, if they all are on the same power supply),
then your collision handling won't work well at all. (In that
case, using the machines IP or MAC address is a much better
idea.) If you're starting a couple of separate processes, each
with it's own generator, for some sort of simulation, time()
probably isn't a good idea either (since it would result in all
processes using the same seed)---in that case getpid() is
suggested. In my case, the code is in a library, and I don't
know what it is going to be used for. So I use the above,
except that in place of time(), I use a hash of time(),
getpid(), and the machine's IP address, hoping to cover all
eventualities.

But as I said, for most uses (games, etc.), time() alone is
perfectly fine.
 
J

James Kanze

[...]
No, that's not correct. The numbers are not guaranteed to be
unique during picking RAND_MAX numbers. Some will repeat,
some will not come up.

And some may never come up, ever:).

What is certain is that the period cannot be longer than the
state. What is also certain is that the standard makes no
guarantees with regards to either, and that I've yet to see an
implementation which does either.
There is no need to reseed the generator. The sequence can be
good enough for picking out of many more (that's controlled by
the generator's "period" characteristic and needn't be linked
to the RAND_MAX value at all.

If the period is not an integral multiple of RAND_MAX+1, then some
values must come up more often than others. (Whether that's
relevant for any particular use, of course, is another question.
With a good 32 bit generator, and a RAND_MAX of around 32000,
we're talking about some values appearing 0.003% more often than
some others.)
Even if you run into a shorter period PRNG, you can always
generate several sequences and then interleave them with each
other to get a relatively random final set.

This is pretty much standard procedure anyway. The classical
linear congruent generators aren't really that random in the
upper bits: a very small value will always be followed by a very
big one. So you keep a table of values, using one generator to
create the elements, and another to choose which one you use.
There are many good PRNGs on the 'net, pick one that suits
your needs, but first you need to prove that the built-in is
not going to suit you.

No. First you have to prove that the built-in one is adequate.
The standard doesn't guarantee it, and historically, they
generally haven't been. (Of course, before that, you have to
define what "adequate" is. That depends on the application.)
There is no indicator to that yet, AFAICT (aside from your
doubt in its capabilities).

History. And the fact that its characteristics aren't
documented, either in the standard or in any implementation
specific documentation that I can see.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top