Mirek said:
A modulo operation is a common advise for generating random numbers within
limited range: random()%r
I've profiled my program and found that % consumes about 30% cpu time.
Is there an another method?
I have two such expression: one has r < 10^5 and the second range can be up
to RAND_MAX. They will be calculated very often - I assume much more than
10^9 times.
Any better solutions?
One can try a quick and dirty pseudo-random generator
found in Numerical Recipe in C...
If r is a number in the range [0..R[
then r/(R+1) is in the range [0..1[
and n*r/(R+1) is in the range [0..n[
and if (R+1) is a power of 2, say R+1=2**p
then (n*r)>>p is in the range [0..n[
For p==32,
one can first generate numbers r in the range [0..2**64[
with a series of the form r_k= r_{k-1} * A + B
(on unsigned long long integers),
and use the 32 hi-bits of r_k for r, leading to:
(n * (r_k >> 32 & 0xFFFFFFFFULL)) >> 32 & 0xFFFFFFFULL,
a formula without any modulo operator...
-----
#define ADD_TERM 0x14A37B71ULL
#define MUL_TERM 0x0004F273ULL
#define MASK 0xFFFFFFFFULL
typedef unsigned long long ULongLong;
typedef unsigned long ULong;
static ULongLong seed, term;
ULong alt_srand (ULong seedi) {
seed= ((ULongLong) seedi) << 32;
term= seed * MUL_TERM + ADD_TERM;
}
ULong alt_rand (ULong range) {
term= term * MUL_TERM + ADD_TERM;
return range * (term >> 32 & MASK) >> 32 & MASK;
}
-----
On my machine with, generating 10**9 numbers in the range [0..13[
using alt_rand(13) vs rand()%13
gives for different optimisation levels:
compiled with gcc -O2: 12.8 sec vs 34.8 sec -> 2.8 x faster.
compiled with gcc -O3: 4.4 sec vs 34.8 sec-> 7.9 x faster.
How bad the generator behaves is another story...