Standard C rand() is based on a Linear Congruential sequence. Such a sequence is known to produce highly non-random low-order bits. In particular, the least bit will strictly alternate between one and zero on successive calls to rand(). This implies that the modulus is not really the most effective way to reduce the range of values produced.
A better way is to use division and keep the quotient. The quotient is strongly influenced by the highest order bits, and is more therefore more random than the remainder (modulus).
For example, assuming RAND_MAX fits in a short, the following will produce a random short in the range [low,high). Generalizing to a RAND_MAX that fits in a long is left as an exercise, but be sure to worry about arithmetic overflow in the multiply. Depending on your hardware and application, it may be easier to do the arithmetic in floating point and cast back to a suitable integer at the end.
short ranged_rand(short low, short high)
{
long r = rand() * (long)(high-low);
r /= RAND_MAX;
r += low;
return (short)r;
}
I suppose I should admit that the above fragment has never seen a compiler, and therefore probably has at least one typo or outright mistake lurking. Another exercise for the reader :-) |