A somewhat late answer, but it should provide some additional
information if the quality of the generation is important. (Not all
applications need this—a slight bias is often not a problem.)
First, of course, the problem in the original code is the fact that
range * rand()
has precedence over the following division, and is done
using integer arithmetic. Depending on RAND_MAX
, this can easily
result in overflow, with implementation defined results; on all
implementations that I know, if it does result in overflow (because
RAND_MAX > INT_MAX / range
, the actual results will almost certainly
be smaller than RAND_MAX + 1.0
, and the division will result in a
value less than 1.0
. There are several ways of avoiding this: the
simplest and most reliable is simply rand() % range + lowest
.
Note that this supposes that rand()
is of reasonable quality. Many
earlier implementations weren't, and I've seen at least one where
rand() % 6 + 1
to simulate a dice throw alternated odd and even. The
only correct solution here is to get a better implementation of
rand()
; it has lead to people trying alternative solutions, such as
(range * (rand() / (RAND_MAX + 1.0))) + lowest
. This masks the
problem, but it won't change a bad generator into a good one.
A second issue, if the quality of the generation is important, is
that when generating random integers, you're discretizing: if you're
simulating the throw of a die, for example, you have six possible
values, which you want to occur with equal probability. The random
generator will generate RAND_MAX + 1
different values, with equal
probability. If RAND_MAX + 1
is not a multiple of 6, there's no
possible way of distributing the values equaly amont the 6 desired
values. Imagine the simple case where RAND_MAX + 1
is 10. Using the
%
method above, the values 1–4 are twice as likely as the the
values 5 and 6. If you use the more complicated formula 1 + int(6 *
(rand() / (RAND_MAX + 1.0)))
(in the case where RAND_MAX + 1 == 10
,
it turns out that 3 and 6 are only half as likely as the other values.
Mathematically, there's simply no way of distributing 10 different
values into 6 slots with an equal number of elements in each slot.
Of course, RAND_MAX
will always be considerably larger than 10, and
the bias introduced will be considerably less; if the range is
significantly less than RAND_MAX
, it could be acceptable. If it's
not, however, the usual procedure is something like:
int limit = (RAND_MAX + 1LL) - (RAND_MAX + 1LL) % range;
// 1LL will prevent overflow on most machines.
int result = rand();
while ( result >= limit ) {
result = rand();
}
return result % range + lowest;
(There are several ways of determining the values to throw out. This
happens to be the one I use, but I remember Andy Koenig using something
completely different—but which resulted in the same values being
thrown out in the end.)
Note that most of the time, you won't enter the loop; the worst case is
when range
is (RAND_MAX + 1) / 2 + 1
, in which case, you'll still
average just under one time through the loop.
Note that these comments only apply when you need a fixed number of
discrete results. For the (other) common case of generating a random
floating point number in the range of [0,1)
, rand() / (RAND_MAX +
1.0)
is about as good as you're going to get.