srand in c or c++ doesn't really Generate Random Numbers ?

C

Chelong

Hi All
I am using the srand function generate random numbers.Here is the
problem.

for example:
#include<iostream>
#include <time.h>

int main()
{
int i = 0,j = 0;

srand((int)time(0));

for(i=0; i<10; i++)
{
j=1+(int)(10.0*rand()/(RAND_MAX+1.0));
std::cout << j << '\t';
}
std::cout << std::endl;
return 0;
}
result£º
5 8 8 8 10 2 10 8 9 9
2 9 7 4 10 3 2 10 8 7

The problem is that the two lines of the result are the same when the
compiler run over in one seconds.
How the function works?
how the computer make the rand numbers?
Does the function can generate really Random Numbers ?

Please help me out if you find some solution for the above problem.
Thanks in advancs !
 
N

Neelesh Bodas

Hi All
I am using the srand function generate random numbers.Here is the
problem.

srand((int)time(0));
[code chopped]
for(i=0; i<10; i++)
{
j=1+(int)(10.0*rand()/(RAND_MAX+1.0));

The problem is that the two lines of the result are the same when the
compiler run over in one seconds.

time() returns time in seconds. If the seed for srand is same, the
same random number sequence will be returned. When your program runs
twice in 1 sec, the seed to srand is same and thus you get the same
sequence.
How the function works?
how the computer make the rand numbers?
Does the function can generate really Random Numbers ?

they are "pseudo" random numbers.

-Neelesh
 
H

Hari

Chelong je napisao:
Hi All
I am using the srand function generate random numbers.Here is the
problem.

for example:
#include<iostream>
#include <time.h>

int main()
{
int i = 0,j = 0;

srand((int)time(0));

for(i=0; i<10; i++)
{
j=1+(int)(10.0*rand()/(RAND_MAX+1.0));
std::cout << j << '\t';
}
std::cout << std::endl;
return 0;
}
result£º
5 8 8 8 10 2 10 8 9 9
2 9 7 4 10 3 2 10 8 7

The problem is that the two lines of the result are the same when the
compiler run over in one seconds.
How the function works?
how the computer make the rand numbers?
Does the function can generate really Random Numbers ?

Please help me out if you find some solution for the above problem.
Thanks in advancs !

First: computers can not generate random numbers, instead they
generate
pseudo random numbers (most people call them random numbers).

For decription of srand:
"The pseudo-random number generator is initialized using the argument
passed as seed.
For every different seed value used in a call to srand, the pseudo-
random number generator can be expected to generate a different
succession of results in the subsequent calls to rand.
Two different initializations with the same seed, instructs the pseudo-
random generator to generate the same succession of results for the
subsequent calls to rand in both cases.
If seed is set to 1, the generator is reinitialized to its initial
value and produces the same values as before any call to rand or
srand.
In order to generate random-like numbers, srand is usually initialized
to some distinctive value, like those related with the execution time.
For example, the value returned by the function time (declared in
header <ctime>) is different each second, which is distinctive enough
for most randoming needs."

In your program everithing looks fine, on my compiler runs ok (I got
diferent
numbers).

Probably, problem is in your time on computer, try to call time() and
print results to
see if you get different values. Also, try to call srand with 1, than
2, ... and see
if you get diferent numbers.

Best,
Zaharije Pasalic
 
S

Sherm Pendley

Chelong said:
Please help me out if you find some solution for the above problem.

Have a look at Boost's Random module. It's still a pseudo-random generator,
but there's no way around that without resorting to specialized hardware,
and it's a much better one than most compilers use.

<http://www.boost.org>

Also, from reading the above, I gather that Random is one of several Boost
modules that are included in TR1, so it's reasonably future-proof.

sherm--
 
C

Chelong

Have a look at Boost's Random module. It's still a pseudo-random generator,
but there's no way around that without resorting to specialized hardware,
and it's a much better one than most compilers use.

<http://www.boost.org>

Also, from reading the above, I gather that Random is one of several Boost
modules that are included in TR1, so it's reasonably future-proof.

sherm--

u all right!
thx!
they are "pseudo" random numbers.
 
J

James Kanze

Chelong je napisao:

[...]
First: computers can not generate random numbers, instead they
generate pseudo random numbers (most people call them random
numbers).

That's not quite true. There are numerous sources of entrophy
on a modern machine, and depending on what the hardware
provides, the OS can usually generate truely random numbers.
Not necessarily very rapidly, however. (Measuring the time
between mouse clicks in nanoseconds, for example, and then
taking the low order bits, would be a good example.)

Unix based machines make this available in "/dev/random". Using
it as your random number generator is going to make your program
incredibly slow, but they usually calculate a bit ahead, so you
can read just a couple of bytes, and use that to seed the random
number generator.

Note too that you don't always want real random numbers. Makes
it awfully hard to reproduce errors for debugging:). The usual
solution is to use pseudo-random numbers (like rand()), note the
seed which was used, and provide an option to specify the seed,
which you can use when you encounter a bug.

[...]
In your program everithing looks fine, on my compiler runs ok
(I got diferent numbers).

He said he only got the same numbers when the program was
invoked twice in the same second. Which is what one would
expect. In the absence of "/dev/random", I'll usually bung in a
number of odd values: the time in microseconds, the process id,
the IP or the MAP address of the machine, etc., depending on
what's available, and what the program is designed to do. (If
it's anything interactive, just time(NULL) is probably
sufficient. Since I'm usually counting on getting different
values from programs started by cron jobs at the same time on
different machines, however...)
 
V

vulpes

A quick solution is to use clock() instead of time().

Actually that's not recommended. clock() returns the number of clock
ticks since the _start of the program_ not since epoch or whatever.
Thus it will always give very similar values, because srand is usually
called at the start of the program. It will even give same values
almost always because usually the OS won't do a context switch (or any
other memory tricks) before the srand gets called and so a constant
number of instructions (and clock ticks) gets done before grabbing the
clock() value.

As Chelong says, boost::random is _the_ choice. It uses Mersenne
Twister algorithm which is way better and faster than the basic C/C++
rand().

You should take care when using rand(), because some Windows machines
let the rand() value to be just a two byte short, which sucks. It
doesn't matter usually though. Also, you shouldn't use the same seed
for more than one tenth or hundredth of the rand()'s granularity. So
for a four byte rand() you shouldn't generate more than ten million
random numbers with the same seed. This sounds pretty stupid, but many
number-crunching programs (such as those I have to write once in a
while) actually may use billions of random numbers. This does not
apply to the boost::random library's Mersenne Twister as you won't
need that many random numbers in your life as that algorithm can
generate before the randomness breaks.
 
J

Jim Langston

vulpes said:
Actually that's not recommended. clock() returns the number of clock
ticks since the _start of the program_ not since epoch or whatever.
Thus it will always give very similar values, because srand is usually
called at the start of the program. It will even give same values
almost always because usually the OS won't do a context switch (or any
other memory tricks) before the srand gets called and so a constant
number of instructions (and clock ticks) gets done before grabbing the
clock() value.

As Chelong says, boost::random is _the_ choice. It uses Mersenne
Twister algorithm which is way better and faster than the basic C/C++
rand().

You should take care when using rand(), because some Windows machines
let the rand() value to be just a two byte short, which sucks. It
doesn't matter usually though. Also, you shouldn't use the same seed
for more than one tenth or hundredth of the rand()'s granularity. So
for a four byte rand() you shouldn't generate more than ten million
random numbers with the same seed. This sounds pretty stupid, but many
number-crunching programs (such as those I have to write once in a
while) actually may use billions of random numbers. This does not
apply to the boost::random library's Mersenne Twister as you won't
need that many random numbers in your life as that algorithm can
generate before the randomness breaks.

It seems that time() + clock() would do the trick, no?
 
P

Pete Becker

As Chelong says, boost::random is _the_ choice. It uses Mersenne
Twister algorithm which is way better and faster than the basic C/C++
rand().

There is no boost::random class or template. There are a handful of
random number generators in Boost, and they've been incorporated into
TR1. mersenne_twister is one of them. Whether it's "way better" depends
on your application. It's certainly much bigger than the typical C
implementation of rand, both in the size of its code and in the amount
of data that it stores.
You should take care when using rand(), because some Windows machines
let the rand() value to be just a two byte short, which sucks. It
doesn't matter usually though.

Well, if it usually doesn't matter, then it doesn't categorically "suck."
Also, you shouldn't use the same seed
for more than one tenth or hundredth of the rand()'s granularity. So
for a four byte rand() you shouldn't generate more than ten million
random numbers with the same seed. This sounds pretty stupid, but many
number-crunching programs (such as those I have to write once in a
while) actually may use billions of random numbers. This does not
apply to the boost::random library's Mersenne Twister as you won't
need that many random numbers in your life as that algorithm can
generate before the randomness breaks.

Okay, so you shouldn't do it, except when it's okay to do it.

Bottom line: choosing a random number generator requires far more data
than is present here, and sweeping generalities aren't helpful.
 
J

James Kanze

A quick solution is to use clock() instead of time().
[/QUOTE]
Actually that's not recommended. clock() returns the number of clock
ticks since the _start of the program_ not since epoch or whatever.
Thus it will always give very similar values, because srand is usually
called at the start of the program. It will even give same values
almost always because usually the OS won't do a context switch (or any
other memory tricks) before the srand gets called and so a constant
number of instructions (and clock ticks) gets done before grabbing the
clock() value.

It's worse. The start time is only "related only to the program
invocation". At least under Solaris, the first call to clock()
always returns 0.

There are a number of system dependant solutions; under Unix,
for example, you can open "/dev/random", and read a couple of
bytes, or use gettimeofday to get the time in microseconds (but
the actual granularity won't be that fine). Hashing in a number
of various values, like the process id and the machine map
address, can be used as well.
As Chelong says, boost::random is _the_ choice. It uses Mersenne
Twister algorithm which is way better and faster than the basic C/C++
rand().

Boost random is a component, not a single class. You choose the
algorithm, and all of the algorithms require a seed, so using
Boost doesn't affect the problem the original poster had. I'm
curious about "faster" as well. A linear congruent generator is
just a multiplication and a modulo; the Mersenne twister seems
to do a lot more operations than just those. So if your machine
has good 64 bit hardware multiply and divide, the minimum
standard generator should be a lot faster. (This will obviously
depend on the machine, of course.)

Independantly of the speed, of course, rand() is often poorly
implemented, and you're better off using one of the Boost
algorithms, all of which have specified behavior, so you can
know what you are getting.
You should take care when using rand(), because some Windows machines
let the rand() value to be just a two byte short, which sucks.

For historical reasons, any number of machines declare RAND_MAX
to be 32767. For historical reasons, a lot of machines have a
very poor rand().
It doesn't matter usually though. Also, you shouldn't use the
same seed for more than one tenth or hundredth of the rand()'s
granularity.

What do you mean by granularity? Obviously, you don't want to
use more than a small part of the generator's cycle, but it's
fairly simple to combine generators if you need a longer cycle.
Or use the lagged fibonacci from boost. (In practice, it
depends on your needs. For most interactive game playing, I
would guess that the period of any of the Boost algorithms would
be sufficient.)
 
J

James Kanze


[...]
It seems that time() + clock() would do the trick, no?

Under Solaris, the first call to clock() always returns 0. If
you're running on the same machine, getpid() (Unix) or
GetCurrentProcessId() (Windows), should provide enough
additional differentiation; if you're worried about the same
seed on different processors, you can throw in the MAP address
or the IP address as well. Both systems also provide the time
with additional precision (gettimeofday(), under Unix, or
GetSystemTime() under Windows).

Also, I'd use some sort of hash code for combining them, and not
just adding.
 

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

Forum statistics

Threads
473,755
Messages
2,569,538
Members
45,024
Latest member
ARDU_PROgrammER

Latest Threads

Top