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?
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?
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.
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)]; int r = (long long)rand() * BOUND / RAND_MAX; causes an unneeded distribution bias and can leave r with the value of BOUND. This could be fixed with int r = (long long)rand() * BOUND / (RAND_MAX + 1LL);.