random number geneator

S

Sonoman

Hi all:
I am trying to write a simple program that simulates asking several persons
their birth day and it counts how many persons are asked until two have the
same birth day. The problem that I have is that the first loop I get a
sequence of random numbers untuil I get a match, BUT then on the following
loops I get the SAME random(?) sequence. I am using rand(). I do not want to
get too fancy with the random number generator, but is there a way of
stopping rand() from resetting every time it starts the loop? What other
choices do I have? Can I somehow use the system time to help me get more
random? Here is my code so far:

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
int const tests = 10000;
int index;
int i,j;
int match = 0;
int days[366] = {0};
int count = 0;

for (j = 1; j <= tests; j++)
{
while (match != 1)
{
index = (rand() % 365) + 1;

if (days[index] != 1)
{
days[index]++;
count++;
}
else
{
for (i = 1; i < 366; i++)
{
days = 0;
}

match = 1;
}

}

cout << count << endl;
}

return 0;
}
 
B

Bruce

In comp.lang.c++
Sonoman said:
get too fancy with the random number generator, but is there a way of
stopping rand() from resetting every time it starts the loop? What other
choices do I have? Can I somehow use the system time to help me get more
random?

Yes, add ONE call like this:

srand(time(NULL));

and your done.
 
P

Pierre Espenan

----- Original Message -----
From: "Sonoman" <[email protected]>
Newsgroups: comp.lang.c++
Sent: Wednesday, January 07, 2004 6:25 PM
Subject: random number geneator

Hi all:
I am trying to write a simple program that simulates asking several persons
their birth day and it counts how many persons are asked until two have the
same birth day. The problem that I have is that the first loop I get a
sequence of random numbers untuil I get a match, BUT then on the following
loops I get the SAME random(?) sequence. I am using rand(). I do not want to
get too fancy with the random number generator, but is there a way of
stopping rand() from resetting every time it starts the loop? What other
choices do I have? Can I somehow use the system time to help me get more
random? Here is my code so far:

#include <iostream>
#include <cstdlib>

add the header said:
using namespace std;

int main()
{
int const tests = 10000;
int index;
int i,j;
int match = 0;
int days[366] = {0};
int count = 0;

for (j = 1; j <= tests; j++)
{
while (match != 1)

at the begining of the loop add,
"srand(clock());"
{
index = (rand() % 365) + 1;

if (days[index] != 1)
{
days[index]++;
count++;
}
else
{
for (i = 1; i < 366; i++)
{
days = 0;
}

match = 1;
}

}

Here you need to put something to change the "seed" in the
"srand(clock());" statement, for example a counter that
requires said:
cout << count << endl;
}

I think you wanted the last "}" bracket above "cout << count << endl;"
return 0;
}

Keep in mind that these are still pseudorandom numbers, but at least the
seed will be changed by pressing the <Enter>.
 
C

Chris Theis

Pierre Espenan said:
[SNIP]
for (j = 1; j <= tests; j++)
{
while (match != 1)

at the begining of the loop add,
"srand(clock());"

This advice is a bad, bad idea regarding randomness. srand should be called
only once(!!) in a program and NEVER inside a loop. The reason is that
calling srand once will yield in a start seed that defines the sequence of
random numbers produced. After calling rand() the internal seed is updated
so that the next call or rand() will result in the next random number of
this specific sequence. If you call srand() more often you are going to jump
from sequence to sequence which will certainly destroy randomness. Although
for this case it might not be a real problem you should refrain from
multiple calls to srand, unless you know exactly what you are doing and what
the results are.

Regards
Chris
 
M

Martijn Lievaart

In comp.lang.c++


Yes, add ONE call like this:

srand(time(NULL));

and your done.

Sound advice, but be aware that time() has low granularity. You may want
to mix in some (platform specific) other elements, like the PID of your
program, or hash the output from netstat and add that. If your program is
designed to run very shortly, this becomes important.

I once was bitten by repeated runs of a program giving exactly the same
results as time() changed only once a second and typically several runs of
the program could be completed in that one second.

Also be aware that many rand() implementations are very poor. For a
typical game this may be acceptable, but for cryptographic operations one
should use some better pseudo random generator (PRNG).

If you really need better random numbers, also have a look at EGD.

HTH,
M4
 
M

MPBroida

Chris said:
Pierre Espenan said:
[SNIP]
for (j = 1; j <= tests; j++)
{
while (match != 1)

at the begining of the loop add,
"srand(clock());"

This advice is a bad, bad idea regarding randomness. srand should be called
only once(!!) in a program and NEVER inside a loop. The reason is that
calling srand once will yield in a start seed that defines the sequence of
random numbers produced. After calling rand() the internal seed is updated
so that the next call or rand() will result in the next random number of
this specific sequence. If you call srand() more often you are going to jump
from sequence to sequence which will certainly destroy randomness. Although
for this case it might not be a real problem you should refrain from
multiple calls to srand, unless you know exactly what you are doing and what
the results are.

In addition, calling srand() only once allows you to replace
the "clock()" call with some constant so you can get REPEATABLE
sequences of random number for testing purposes. AFTER testing
is completed, restore the clock() call (or something similar).

Mike
 
P

Pierre Espenan

Chris Theis said:
Pierre Espenan said:
[SNIP]
for (j = 1; j <= tests; j++)
{
while (match != 1)

at the begining of the loop add,
"srand(clock());"

This advice is a bad, bad idea regarding randomness. srand should be called
only once(!!) in a program and NEVER inside a loop. The reason is that
calling srand once will yield in a start seed that defines the sequence of
random numbers produced. After calling rand() the internal seed is updated
so that the next call or rand() will result in the next random number of
this specific sequence. If you call srand() more often you are going to jump
from sequence to sequence which will certainly destroy randomness. Although
for this case it might not be a real problem you should refrain from
multiple calls to srand, unless you know exactly what you are doing and what
the results are.

Did you actually try to compile and run the code listed? Did you see what
he is talking about? The same number is generated by rand() in each loop
because the loop has a constant relationship to clock(). Puting in
cin.get() into the loop insures that a different seed is generated each
loop. I ran the modified program for 100 loops and the average for count
came out to 24 which is very close to the average expected by strict
mathematical analysis. The reason srand(clock()) is discouraged within a
loop is that unless special care is taken a new seed will not be generated.
Run the following code and see what happens...

#include <iostream>
#include <ctime>
#include <bitset>

using namespace std;

int main(){
bitset<365> date;
while(1){
srand(clock());
for(int count=1,i=0; ; ++count){
i=rand()%365;
if(date.test(i)) break;
date.flip(i);
}
cout << count << '\n';
date.reset();
cin.get();
}
return 0;
}
 
K

Karl Heinz Buchegger

Pierre said:
Chris Theis said:
Pierre Espenan said:
[SNIP]

for (j = 1; j <= tests; j++)
{
while (match != 1)

at the begining of the loop add,
"srand(clock());"

This advice is a bad, bad idea regarding randomness. srand should be called
only once(!!) in a program and NEVER inside a loop. The reason is that
calling srand once will yield in a start seed that defines the sequence of
random numbers produced. After calling rand() the internal seed is updated
so that the next call or rand() will result in the next random number of
this specific sequence. If you call srand() more often you are going to jump
from sequence to sequence which will certainly destroy randomness. Although
for this case it might not be a real problem you should refrain from
multiple calls to srand, unless you know exactly what you are doing and what
the results are.

Did you actually try to compile and run the code listed?

Did you ever read the documentation for rand()?
If you call rand(), it will also update the seed value. Thus when calling
rand() the next time, it will generate a different random number (and
update the seed value again) such that when calling rand() the next time
a different random value is generated (and the seed is updated again) etc.

It is important to let rand() do this in its own, because randomness in
a computer is a statistical property. If you reseed the random number
generator to often, this statistical property cannot build up (as with
all statistics, it works only for a sufficient large number of samples,
in this case a sufficient large number of random values).
Did you see what
he is talking about? The same number is generated by rand() in each loop
because the loop has a constant relationship to clock().

It doesn't matter. The main problem is, that srand() should be called only
once (!) in a program, not often, especially not before every call to rand()!
BTW: The original code didn't have a call to srand() at all. Thus there could
not have been any realtionship to clock() (which was also not in the original
code).

Common practice is to not use clock() for seeding the random number generator
but using time() to do that.
Puting in
cin.get() into the loop insures that a different seed is generated each
loop.

And how does this help in a program which should run on it's own without
a user?
I ran the modified program for 100 loops and the average for count
came out to 24 which is very close to the average expected by strict
mathematical analysis. The reason srand(clock()) is discouraged within a
loop is that unless special care is taken a new seed will not be generated.

The reason why you shouldn't call srand() more then once is, that you destroy
the randomness of the sequence if you do it. A random number generator is
designed to give a *sequence* of random numbers. It is only the sequence
which shows the properties of randomness. Don't interfere with the
generation of the sequence or you will destroy randomness very easily.
 
P

Pierre Espenan

Karl Heinz Buchegger said:
Pierre said:
Chris Theis said:
[SNIP]

for (j = 1; j <= tests; j++)
{
while (match != 1)

at the begining of the loop add,
"srand(clock());"

This advice is a bad, bad idea regarding randomness. srand should be called
only once(!!) in a program and NEVER inside a loop. The reason is that
calling srand once will yield in a start seed that defines the sequence of
random numbers produced. After calling rand() the internal seed is updated
so that the next call or rand() will result in the next random number of
this specific sequence. If you call srand() more often you are going
to
jump
from sequence to sequence which will certainly destroy randomness. Although
for this case it might not be a real problem you should refrain from
multiple calls to srand, unless you know exactly what you are doing
and
what
the results are.

Did you actually try to compile and run the code listed?

Did you ever read the documentation for rand()?
If you call rand(), it will also update the seed value. Thus when calling
rand() the next time, it will generate a different random number (and
update the seed value again) such that when calling rand() the next time
a different random value is generated (and the seed is updated again) etc.

It is important to let rand() do this in its own, because randomness in
a computer is a statistical property. If you reseed the random number
generator to often, this statistical property cannot build up (as with
all statistics, it works only for a sufficient large number of samples,
in this case a sufficient large number of random values).
Did you see what
he is talking about? The same number is generated by rand() in each loop
because the loop has a constant relationship to clock().

It doesn't matter. The main problem is, that srand() should be called only
once (!) in a program, not often, especially not before every call to rand()!
BTW: The original code didn't have a call to srand() at all. Thus there could
not have been any realtionship to clock() (which was also not in the original
code).

Common practice is to not use clock() for seeding the random number generator
but using time() to do that.

Oops! I tried srand(time(NULL)) outside of the loop and this does yield the
correct result without cin.get() so I guess this is the source of all the
problems
generating (pseudo) random numbers I have been having. I just confused
clock()
with time().
 
S

Sonoman

First of all, Thanks for the help. The srand works better outside the loop.
The first time I ran the program I got a sequence of random numbers. BUT on
the second time and the times after that, when I execute the program I get
the same exact sequence of numbers. Does anyone care to explain why? Any
simple solutions out there? Any clever solutions for my print statement? It
just looks to stupid. Here is my current code:

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
int index;
int i;
double j;
int match = 0;
int days[366] = {0};
double count = 0;
double sum = 0;
double average;

srand(clock());

for (j = 1; j <= 10000; j++)
{
while (match != 1)
{
index = (rand() % 365) + 1;

if (days[index] != 1)
{
days[index]++;
count++;
}
else
{
for (i = 0; i < 366; i++)
{
days = 0;
}

match = 1;
sum = sum + count;
average = sum/j;
}
}

if( j == 1 || j == 2 || j == 3 || j == 4 || j == 5 ||
j == 10 || j == 25 || j == 50 || j == 100 ||
j == 1000 || j == 10000)
{
cout << "test # " << j << " asked " << count <<
" persons, the average so far is: " << average << endl;
}

match = 0;
count = 0;
}

return 0;
}
 
M

Martijn Lievaart

First of all, Thanks for the help. The srand works better outside the loop.
The first time I ran the program I got a sequence of random numbers. BUT on
the second time and the times after that, when I execute the program I get
the same exact sequence of numbers. Does anyone care to explain why? Any
simple solutions out there? Any clever solutions for my print statement? It
just looks to stupid. Here is my current code:

srand(clock());

CLOCK(3) Linux Programmer's Manual CLOCK(3)

NAME
clock - Determine processor time

SYNOPSIS
#include <time.h>

clock_t clock(void);

DESCRIPTION
The clock() function returns an approximation of processor time used by
the program.

Clock() always returns (aproximately) the same number. Use time() instead.

HTH,
M4
 

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,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top