problem with rand()

C

ChasW

given the following example:

Using gcc, this compiles, runs, and outputs as expected, but on
vc++.net 2003, the first number is always the same despite the time
seed.

#include <ctime>
#include <iostream>

using namespace std;

// output 10 numbers ranging from [0, n)
int main ()
{
srand((unsigned int)time(NULL));

int n = 100;

for (int i = 0; i < 10; ++i)
{
cout << int(double(rand()) * n / (RAND_MAX + 1.0)) << "\n";
}
cout << endl;

return 0;
}

What am i doing wrong?
Charles
 
V

Victor Bazarov

given the following example:

Using gcc, this compiles, runs, and outputs as expected, but on
vc++.net 2003, the first number is always the same despite the time
seed.

#include <ctime>
#include <iostream>

using namespace std;

// output 10 numbers ranging from [0, n)
int main ()
{
srand((unsigned int)time(NULL));

int n = 100;

for (int i = 0; i < 10; ++i)
{
cout << int(double(rand()) * n / (RAND_MAX + 1.0)) << "\n";
}
cout << endl;

return 0;
}

What am i doing wrong?

First, let me say that it is quite possible that on some hardware RAND_MAX
cannot be represented precisely as a double making it impossible to add 1.0
to it with any effect. But that's really not the problem.

You're scaling your numbers and throwing away the lower part, which _does_
differ from run to run even on VC++. Just print out 'rand()' instead.

It seems that the implementation of the pseudo-random number generator in
the C library shipped with VC++ is rather poor. Try finding a better one
on the Web, it shouldn't be that hard.

Victor
 
C

ChasW

You're scaling your numbers and throwing away the lower part, which _does_
differ from run to run even on VC++. Just print out 'rand()' instead.

It seems that the implementation of the pseudo-random number generator in
the C library shipped with VC++ is rather poor. Try finding a better one
on the Web, it shouldn't be that hard.

Victor

I see what you mean. When i print out just the rand(), the first of
ten calls is very similar each time the program is run, but it _is_
different as you say. It almost makes me want to wrap rand() and
discard the first number each time it is called, but I shouldnt have
to do that.

This is really an odd problem for VC++.

It seems to also affect this wrapper function as well, which is taken
from Koenig's Accelerated C++.

I realize this code can be somewhat costly timewise, but it did
provide a simple function for improving number distribution.

int nrand(int n)
{
if (n <= 0 || n > RAND_MAX)
throw domain_error("Argument to nrand is out of range");

const int bucket_size = RAND_MAX / n;
int r;

do { r = rand() / bucket_size; }
while (r >= n);

return r;
}

I didnt need to look on the Web, Stroustrup's book has one, but until
now, I havent had to use it.

Cheers,
Charles
 
I

Ioannis Vranos

ChasW said:
I see what you mean. When i print out just the rand(), the first of
ten calls is very similar each time the program is run, but it _is_
different as you say. It almost makes me want to wrap rand() and
discard the first number each time it is called, but I shouldnt have
to do that.

This is really an odd problem for VC++.



I had come to this problem myself, and my quick solution was to omit the
first two calls of rand().

Another system dependent solution is to use a Rand object of .NET. It is
far better than their rand() implementation.
 
C

ChasW

I had come to this problem myself, and my quick solution was to omit the
first two calls of rand().

My issue was with the first call only, and only after setting a time
seed.

An easy solution is to just call rand() one time after calling
srand(). Think of it as a "warm-up"
Another system dependent solution is to use a Rand object of .NET. It is
far better than their rand() implementation.

Stroustrup's random number generator also is quite suitable for my
needs and is portable.

Charles
 
C

Chris Theis

I see what you mean. When i print out just the rand(), the first of
ten calls is very similar each time the program is run, but it _is_
different as you say. It almost makes me want to wrap rand() and
discard the first number each time it is called, but I shouldnt have
to do that.

This is really an odd problem for VC++.

Actually the problem is not odd at all, neither for VC++ nor other rand()
implementations. In general random number generation is a very subtle
problem and many generators suffer from different defects. What you can do
is to use a "warm-up" phase of the generator, which is a common approach
used in some Monte Carlo simulations. Otherwise you could resort to a
"better" generator (without going into details what better means in this
context) like a Mersenne Twister or ran2 from Numerical Recipes. The code
you gave is already an improvement regarding uniformity of the distribution,
but it has runtime drawbacks because its a simple rejection method.

Regards
Chris
 
I

Ioannis Vranos

ChasW said:
My issue was with the first call only, and only after setting a time
seed.


Yes I am talking about the same case, after a call to srand(time(0));

My experiments showed me that after omitting the first two calls of
rand() after srand(), would improve things (and not one call).
 

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,780
Messages
2,569,611
Members
45,281
Latest member
Pedroaciny

Latest Threads

Top