Reputation: 40245
I was looking for C code to generate a set of random even number in range [start, end]
. I tried,
int random = ((start + rand() % (end - start) / 2)) * 2;
This won't work, for example if the range is [0, 4], both 0 & 4 included
int random = (0 + rand() % (4 - 0) / 2) * 2
=> (rand() % 2) * 2
=> 0, 2, ... (never includes 4) but expectation = 0, 2, 4 ...
On the other hands if I use,
int random = ((start + rand() % (end - start) / 2) + 1) * 2;
This won't work, for example,
int random = (0 + (rand() % (4 - 0) / 2) + 1) * 2
=> ((rand() % 4 / 2) + 1) * 2
=> 2, 4, ... (never includes 0) but expectation = 0, 2, 4 ...
Any clue? how to get rid of this problem?
Upvotes: 0
Views: 4664
Reputation: 232
I do not trust in the mod operator for random numbers. I prefer
start + ((1 + stop - start) * rand())
/ (1 + RAND_MAX)
which only relies on the distribution of rand()
in the interval
[0, .. , RAND_MAX]
and not on any distribution of rand()%n
in the
interval [0, .. , n-1]
.
Note: If you use this expression you should add appropriate casts to avoid multiplication overflow.
Note also ISO/IEC 9899:201x (p.346):
There are no guarantees as to the quality of the random sequence produced and some implementations are known to produce sequences with distressingly non-random low-order bits. Applications with particular requirements should use a generator that is known to be sufficient for their needs.
Upvotes: 1
Reputation: 25286
Just and-out the low bit, which makes it even:
n= (rand()%N)&(-2);
and to use a start/stop (a range), the values can be offset:
int n, start= 5, stop= 20+1;
n= ((rand()%(stop-start))+start)&(-2);
The latter calculation generates a random number between 0 and RAND_MAX (this value is library-dependent, but is guaranteed to be at least 32767).
If the stop value must be included in the range of generated numbers, then add 1 to the stop value.
It takes that value modulo the stop value plus the start value, and then adds the start value. The value is now within the range of [start, stop]. As only even numbers are required, the low bit is anded-out because even numbers start at 2.
The anding-out is performed by generating a mask of all 1's, except the lowest bit. As -1 is all 1's (0xFFF...FFFFF
), -2 is all 1's except this low bit (0xFFF...FFFFE
). Next the bitwise AND
operation (&) is perfomed with this mask and the number is now in the range [start,stop]. QED.
Upvotes: 0
Reputation: 31409
rand() % x
will generate a number in the range [0,x)
so if you want the range [0,x]
then use rand() % (x+1)
Common notation for ranges is to use
[]
for inclusive and()
for exclusive, so[a,b)
would be a range such that a is included but not b.
So in your case, just use (rand() % 3)*2
to get random numbers among {0,2,4}
If you want even numbers in the range [m,n]
, then use ((m/2) + rand() % ((n-m+2)/2))*2
Upvotes: 2
Reputation: 122
You complicated it too much. Since you're using rand()
and the modulo operator, I'm assuming that you will not be using this for cryptographic or security purposes, but as a simple even number generator.
The formula I have found for generating a random even number in the range of [0, 2n] is to use
s = (rand() % (n + 1)) * 2
An example code:
#include <stdio.h>
int main() {
int i, s;
for(i = 0; i < 100; i++) {
s = (rand() % 3) * 2;
printf("%d ", s);
}
}
And it gave me the following output:
2 2 0 2 4 2 2 0 0 2 4 2 4 2 4 2 0 0 2 2 4 4 0 0 4 4 4 2 2 2 4 0 0 0 4 0 2 2 2 2 0 0 0 4 4 2 4 4 4 0 4 2 2 4 4 0 4 4 2 2 0 0 4 0 4 4 2 0 2 4 0 0 0 0 4 0 4 4 0 4 2 0 0 4 4 0 0 4 4 2 0 0 4 0 2 2 2 0 0 4 0 2 4 2
Best regards!
Upvotes: 3