Reputation: 11
So far I have a function which generates a random integer value within a fixed range (Min, Max) and it seems to work. But how can I make it so that if my range was (0,100), the random values returned is always a multiple of 8? (that is uniform intervals)
int generate_rand(int Min, int Max)
{
// Generates random number between min and max, inclusive.
int range, result, cutoff;
if (Min >= Max)
return Min; // only one outcome possible, or invalid parameters
range = Max-Min+1;
cutoff = (RAND_MAX / range) * range;
// Rejection method, to be statistically unbiased.
do {
result = rand();
} while (result >= cutoff);
return result % range + Min;
}
The same for the code below. How can I make the RANDOM_NUM variable to always be a multiple of 20/3 every time I call it? This one generates a random float value between 0 and 1. (that is uniform intervals)
RANDOM_NUM = ((float)rand()/(float)(RAND_MAX+1));
Upvotes: 1
Views: 257
Reputation: 34585
"How can I make the RANDOM_NUM
variable to always be a multiple of 20/3 every time I call it?"
I used double
in preference to float
due to its greater precision, but even so there cannot be a guarantee of an exact multiple, as this program shows. When tested, in some cases the remainder is 0, in the others it is apparently, and absurdly 6.666667, which is 20/3. This is due to the fact that not all numbers can be precisely represented in floating point format.
In decimal point notation the result of the division 1/3 has a recurrent one digit 0.333333~
which in binary point notation has a recurrent 2 digits 0.010101~~
.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define NUMERATOR 20
#define DENOMINATOR 3
double randnum(int numerator, int denominator) {
return (double)rand() * (double)numerator / (double)denominator;
}
int main(void) {
int i;
double random_num, remainder;
srand ((unsigned)time(NULL));
for (i=0; i<10; i++) {
random_num = randnum(NUMERATOR, DENOMINATOR);
remainder = fmod(random_num, (double)NUMERATOR / (double)DENOMINATOR);
printf("%-16f %f\n", random_num, remainder);
}
return 0;
}
Program output (random number, remainder):
72706.666667 0.000000
209733.333333 0.000000
170686.666667 6.666667
187546.666667 6.666667
121093.333333 6.666667
116660.000000 6.666667
75646.666667 0.000000
64960.000000 6.666667
186653.333333 0.000000
159713.333333 0.000000
Upvotes: 1
Reputation: 505
You could get a random number in the range 0-13 and then multiply your result by 8. It would be in the range [0, 104]. You could do the same thing for 20/3. Assuming you only take integer results, which appears to be true, this would always work.
Upvotes: 0
Reputation: 529
The fastest solution would be to just set the three lowest bits of the integer to zero: rand &= ~0x07
. (Assuming that rand
is an integer between 0 and 100.)
Of course that does not apply if you want it to be multiple of a number that is not a power of two and it is hard to read if you're not familiar with bit operations (a comment could not hurt).
Upvotes: 0
Reputation: 533
Assuming that rand is your random integer between 0 and 100 :
rand = rand - (rand % 8);
Upvotes: 0
Reputation: 206577
But how can I make it so that if my range was (0,100), the random values returned is always a multiple of 8?
return ((result % range + Min)/8)*8;
Upvotes: 1