Francesco Bonizzi
Francesco Bonizzi

Reputation: 5302

Extend rand() max range

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!

Upvotes: 5

Views: 18640

Answers (5)

Kerrek SB
Kerrek SB

Reputation: 477434

Scale your numbers up by N / RAND_MAX, where N is your desired maximum. If the numbers fit, you can do something like this:

unsigned long long int r = rand() * N / RAND_MAX;

Obviously if the initial part overflows you can't do this, but with N = 250000 you should be fine. RAND_MAX is 32K on many popular platforms.

More generally, to get a random number uniformly in the interval [A, B], use:

A + rand() * (B - A) / RAND_MAX;

Of course you should probably use the proper C++-style <random> library; search this site for many similar questions explaining how to use it.


Edit: In the hope of preventing an escalation of comments, here's yet another copy/paste of the Proper C++ solution for truly uniform distribution on an interval [A, B]:

#include <random>

typedef std::mt19937 rng_type;
typedef unsigned long int int_type;  // anything you like

std::uniform_int_distribution<int_type> udist(A, B);
rng_type rng;

int main()
{
    // seed rng first:
    rng_type::result_type const seedval = get_seed();
    rng.seed(seedval);

    int_type random_number = udist(rng);
    // use random_number
}

Don't forget to seend the RNG! If you store the seed value, you can replay the same random sequence later on.

Upvotes: 0

0-0
0-0

Reputation: 482

Are you using short ints? If so, you will see 32,767 as your max number because anything larger will overflow the short int.

Upvotes: 0

Heinzi
Heinzi

Reputation: 6091

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

Upvotes: 10

Stefan Marinov
Stefan Marinov

Reputation: 581

You can just manipulate your number bitwise by generating smaller random numbers.

For instance, if you need a 32-bit random number:

int32 x = 0;
for (int i = 0; i < 4; ++i) { // 4 == 32/8
   int8 tmp = 8bit_random_number_generator();
   x <<= 8*i; x |= tmp;
}

If you don't need good randomness in your numbers, you can just use rand() & 0xff for the 8-bit random number generator. Otherwise, something better will be necessary.

Upvotes: 1

James Kanze
James Kanze

Reputation: 154007

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.

Upvotes: 3

Related Questions