This is a follow on from a previously posted question:
How to generate a random number in C?
I wish to be able to generate a random number from within a particular range, such as 1 to 6 to mimic the sides of a die.
How would I go about doing this?
Best Answer
All the answers so far are mathematically wrong. Returning
rand() % N
does not uniformly give a number in the range[0, N)
unlessN
divides the length of the interval into whichrand()
returns (i.e. is a power of 2). Furthermore, one has no idea whether the moduli ofrand()
are independent: it's possible that they go0, 1, 2, ...
, which is uniform but not very random. The only assumption it seems reasonable to make is thatrand()
puts out a Poisson distribution: any two nonoverlapping subintervals of the same size are equally likely and independent. For a finite set of values, this implies a uniform distribution and also ensures that the values ofrand()
are nicely scattered.This means that the only correct way of changing the range of
rand()
is to divide it into boxes; for example, ifRAND_MAX == 11
and you want a range of1..6
, you should assign{0,1}
to 1,{2,3}
to 2, and so on. These are disjoint, equally-sized intervals and thus are uniformly and independently distributed.The suggestion to use floating-point division is mathematically plausible but suffers from rounding issues in principle. Perhaps
double
is high-enough precision to make it work; perhaps not. I don't know and I don't want to have to figure it out; in any case, the answer is system-dependent.The correct way is to use integer arithmetic. That is, you want something like the following:
The loop is necessary to get a perfectly uniform distribution. For example, if you are given random numbers from 0 to 2 and you want only ones from 0 to 1, you just keep pulling until you don't get a 2; it's not hard to check that this gives 0 or 1 with equal probability. This method is also described in the link that nos gave in their answer, though coded differently. I'm using
random()
rather thanrand()
as it has a better distribution (as noted by the man page forrand()
).If you want to get random values outside the default range
[0, RAND_MAX]
, then you have to do something tricky. Perhaps the most expedient is to define a functionrandom_extended()
that pullsn
bits (usingrandom_at_most()
) and returns in[0, 2**n)
, and then applyrandom_at_most()
withrandom_extended()
in place ofrandom()
(and2**n - 1
in place ofRAND_MAX
) to pull a random value less than2**n
, assuming you have a numerical type that can hold such a value. Finally, of course, you can get values in[min, max]
usingmin + random_at_most(max - min)
, including negative values.