Reputation: 15335
Is there a better way than:
#define BOUND 7
int r;
int e = 1;
r = rand() % BOUND;
while (r == e){
r = rand() % BOUND;
}
for generating numbers in a range except for a value e
?
Upvotes: 3
Views: 374
Reputation: 144715
To generate a pseudo-random number in a range with a uniform distribution among values, it is much more reliable to use the magnitude of the value returned by rand()
rather than its remainder for the division rand() % BOUND
:
int r = (long long)rand() * BOUND / (RAND_MAX + 1LL);
rand()
returns a value between 0
and RAND_MAX
included: the division must use RAND_MAX + 1LL
so the result is in range 0
included .. BOUND
excluded (as commented by chux).
If you want to exclude a given value, reduce the range by one and adjust the result:
#define BOUND 7
int r = (long long)rand() * (BOUND - 1) / (RAND_MAX + 1LL);
if (r >= 1) { // shift values 1..5 to 2..6
r += 1;
}
Here is a more general version:
// select a random value from a set
int set[] = { 0, 2, 3, 4, 5, 6 };
int r = set[(long long)rand() * (sizeof(set) / sizeof(*set)) / (RAND_MAX + 1LL)];
Upvotes: 5
Reputation: 20705
What you're asking for is generating a random number in the range [0, BOUND)
excluding the value e
The algorithm explained here seems to be the best way to do it without using a loop.
Here is the C code:
#define BOUND 7
int r;
int e = 1;
r = rand() % (BOUND-1);
if (r >= e){
r = r+1;
}
So, you basically generate a value in the range [0, BOUND-1)
, and if the value is greater than or equal to the excluded value e
, you increment the random number by one.
Keep in mind that using rand
with %
does not guarantee a strict uniform distribution across the generated numbers. For more info, check out this question/answers.
Upvotes: 10