Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extend rand() max range

Tags:

c++

I created a test application that generates 10k random numbers in a range from 0 to 250 000. Then I calculated MAX and min values and noticed that the MAX value is always around 32k...

Do you have any idea how to extend the possible range? I need a range with MAX value around 250 000!

like image 541
Francesco Bonizzi Avatar asked Mar 19 '12 17:03

Francesco Bonizzi


2 Answers

This is according to the definition of rand(), see:

http://cplusplus.com/reference/clibrary/cstdlib/rand/

http://cplusplus.com/reference/clibrary/cstdlib/RAND_MAX/

If you need larger random numbers, you can use an external library (for example http://www.boost.org/doc/libs/1_49_0/doc/html/boost_random.html) or calculate large random numbers out of multiple small random numbers by yourself.

But pay attention to the distribution you want to get. If you just sum up the small random numbers, the result will not be equally distributed.

If you just scale one small random number by a constant factor, there will be gaps between the possible values.

Taking the product of random numbers also doesn't work.

A possible solution is the following:

1) Take two random numbers a,b
2) Calculate a*(RAND_MAX+1)+b

So you get equally distributed random values up to (RAND_MAX+1)^2-1

like image 113
Heinzi Avatar answered Sep 28 '22 15:09

Heinzi


Presumably, you also want an equal distribution over this extended range. About the only way you can effectively do this is to generate a sequence of smaller numbers, and scale them as if you were working in a different base. For example, for 250000, you might 4 random numbers in the range [0,10) and one in range [0,25), along the lines:

int
random250000()
{
    return randomInt(10) + 10 * randomInt(10)
        + 100 * randomInt(10) + 1000 * randomInt(10)
        + 10000 * randomInt(25);
}

For this to work, your random number generator must be good; many implementations of rand() aren't (or at least weren't—I've not verified the situation recently). You'll also want to eliminate the bias you get when you map RAND_MAX + 1 different values into 10 or 25 different values. Unless RAND_MAX + 1 is an exact multiple of 10 and 25 (e.g. is an exact multiple of 50), you'll need something like:

int
randomInt( int upperLimit )
{
    int const limit = (RAND_MAX + 1) - (RAND_MAX + 1) % upperLimit;
    int result = rand();
    while ( result >= limit ) {
        result = rand();
    return result % upperLimit;
}

(Attention when doing this: there are some machines where RAND_MAX + 1 will overflow; if portability is an issue, you'll need to take additional precautions.)

All of this, of course, supposes a good quality generator, which is far from a given.

like image 36
James Kanze Avatar answered Sep 28 '22 16:09

James Kanze