Reputation: 495
I would like to generate some random numbers, say from min
to max
. The problem is that rand()
generates numbers in the range [0, RAND_MAX]
. Scaling this to [min, max]
leads to a range of 1 for each number except for max
which occurs once out of RAND_MAX
times. If I make the upper bound max + 1
, I might still get max + 1
as a value. Basically, is there a way to make the range [min, max + 1)
?
Here's some code I have:
int u_rand(int min, int max)
{
return (int)((double)rand() / RAND_MAX * (max - min + 1)) + min; //has a chance to spit out max + 1
}
Upvotes: 0
Views: 544
Reputation: 7740
The following should provide a uniform distribution of random numbers from [min, max)
int u_rand(int min, int max) {
int threshold = RAND_MAX - RAND_MAX % (max - min);
int num = rand();
while (num >= threshold) {
num = rand();
}
return num % (max - min) + min;
}
It discards part of the range that cannot be equally distributed between [min, max), and if a number is chosen in this range, it will draw a new number instead until it gets one within the acceptable range. This does mean there isn't a hard limit on how long it will take to produce a random number, but statistically it will outperform the deterministic variants. Note I also avoid using floating point arithmetic anywhere, so there's no subtle bias due to rounding there either. Your numbers will be as uniform as the original range rand()
provides.
Upvotes: 2
Reputation: 29332
Your method won't result in a uniform distribution. The closest you can get to a uniform distribution will be using the modulo operator %
.
int u_rand(int min, int max)
{
return min + rand() % (max - min + 1);
}
Again this isn't perfectly uniform but fairly close and simple (assuming that your range max - min
is small compared to RAND_MAX and that rand()
is well implemented).
Upvotes: 2
Reputation:
Short answer: Delete the +1
.
Long answer: The (max - min + 1)
calculates the width of the range you're trying to get the number in -- that is, the total number of, er, numbers that it spans. With just that, and no + min
, you get numbers in [0, max-min+1)
. Then + min
offsets that to start at min
, so you end up getting [min, max-min+1+min)
, aka [min, max+1)
, aka [min, max]
. If you want to exclude max
, shrink your range's width by one, but offset it by the same amount:
(int)((double)rand() / RAND_MAX * (max - min)) + min
Upvotes: 0