How do I get a specific range of numbers from rand()?

CRandom

C Problem Overview


srand(time(null));

printf("%d", rand());

Gives a high-range random number (0-32000ish), but I only need about 0-63 or 0-127, though I'm not sure how to go about it. Any help?

C Solutions


Solution 1 - C

rand() % (max_number + 1 - minimum_number) + minimum_number

So, for 0-65:

rand() % (65 + 1 - 0) + 0

(obviously you can leave the 0 off, but it's there for completeness).

Note that this will bias the randomness slightly, but probably not anything to be concerned about if you're not doing something particularly sensitive.

Solution 2 - C

check here

http://c-faq.com/lib/randrange.html

For any of these techniques, it's straightforward to shift the range, if necessary; numbers in the range [M, N] could be generated with something like

M + rand() / (RAND_MAX / (N - M + 1) + 1)

Solution 3 - C

You can use this:

int random(int min, int max){
   return min + rand() / (RAND_MAX / (max - min + 1) + 1);
}

From the: > ## comp.lang.c FAQ list · Question 13.16 >
> ### Q: How can I get random integers in a certain range? > > ### A: The obvious way, > > rand() % N /* POOR */ > > (which tries to return numbers from 0 to N-1) is poor, because the > low-order bits of many random number generators are distressingly > non-random. (See question 13.18.) A better method is something like > > (int)((double)rand() / ((double)RAND_MAX + 1) * N) > > If you'd rather not use floating point, another method is > > rand() / (RAND_MAX / N + 1) > > If you just need to do something with probability 1/N, you could use > > if(rand() < (RAND_MAX+1u) / N) > > All these methods obviously require knowing RAND_MAX (which ANSI #defines in <stdlib.h>), and assume that N is much less than RAND_MAX. When N is close to RAND_MAX, and if the range of the random number > generator is not a multiple of N (i.e. if (RAND_MAX+1) % N != 0), all > of these methods break down: some outputs occur more often than > others. (Using floating point does not help; the problem is that rand > returns RAND_MAX+1 distinct values, which cannot always be evenly > divvied up into N buckets.) If this is a problem, about the only thing > you can do is to call rand multiple times, discarding certain values: > > unsigned int x = (RAND_MAX + 1u) / N; > unsigned int y = x * N; > unsigned int r; > do { > r = rand(); > } while(r >= y); > return r / x; > > For any of these techniques, it's straightforward to shift the range, > if necessary; numbers in the range [M, N] could be generated with > something like > > M + rand() / (RAND_MAX / (N - M + 1) + 1) > > (Note, by the way, that RAND_MAX is a constant telling you what the > fixed range of the C library rand function is. You cannot set RAND_MAX > to some other value, and there is no way of requesting that rand > return numbers in some other range.) > > If you're starting with a random number generator which returns > floating-point values between 0 and 1 (such as the last version of > PMrand alluded to in question 13.15, or drand48 in question > 13.21), all you have to do to get integers from 0 to N-1 is > multiply the output of that generator by N: > > (int)(drand48() * N) > > Additional links > > References: K&R2 Sec. 7.8.7 p. 168
> PCS Sec. 11 p. 172

Quote from: http://c-faq.com/lib/randrange.html

Solution 4 - C

Taking the modulo of the result, as the other posters have asserted will give you something that's nearly random, but not perfectly so.

Consider this extreme example, suppose you wanted to simulate a coin toss, returning either 0 or 1. You might do this:

isHeads = ( rand() % 2 ) == 1;

Looks harmless enough, right? Suppose that RAND_MAX is only 3. It's much higher of course, but the point here is that there's a bias when you use a modulus that doesn't evenly divide RAND_MAX. If you want high quality random numbers, you're going to have a problem.

Consider my example. The possible outcomes are:

rand()  freq. rand() % 2
0       1/3   0
1       1/3   1
2       1/3   0

Hence, "tails" will happen twice as often as "heads"!

Mr. Atwood discusses this matter in this Coding Horror Article

Solution 5 - C

The naive way to do it is:

int myRand = rand() % 66; // for 0-65

This will likely be a very slightly non-uniform distribution (depending on your maximum value), but it's pretty close.

To explain why it's not quite uniform, consider this very simplified example:
Suppose RAND_MAX is 4 and you want a number from 0-2. The possible values you can get are shown in this table:

rand()   |  rand() % 3
---------+------------
0        |  0
1        |  1
2        |  2
3        |  0

See the problem? If your maximum value is not an even divisor of RAND_MAX, you'll be more likely to choose small values. However, since RAND_MAX is generally 32767, the bias is likely to be small enough to get away with for most purposes.

There are various ways to get around this problem; see here for an explanation of how Java's Random handles it.

Solution 6 - C

As others have noted, simply using a modulus will skew the probabilities for individual numbers so that smaller numbers are preferred.

A very ingenious and good solution to that problem is used in Java's java.util.Random class:

public int nextInt(int n) {
    if (n <= 0)
        throw new IllegalArgumentException("n must be positive");

    if ((n & -n) == n)  // i.e., n is a power of 2
        return (int)((n * (long)next(31)) >> 31);

    int bits, val;
    do {
        bits = next(31);
        val = bits % n;
    } while (bits - val + (n-1) < 0);
    return val;
}

It took me a while to understand why it works and I leave that as an exercise for the reader but it's a pretty concise solution which will ensure that numbers have equal probabilities.

The important part in that piece of code is the condition for the while loop, which rejects numbers that fall in the range of numbers which otherwise would result in an uneven distribution.

Solution 7 - C

rand() will return numbers between 0 and RAND_MAX, which is at least 32767.

If you want to get a number within a range, you can just use modulo.

int value = rand() % 66; // 0-65

For more accuracy, check out this article. It discusses why modulo is not necessarily good (bad distributions, particularly on the high end), and provides various options.

Solution 8 - C

Updated to not use a #define

double RAND(double min, double max)
{
    return (double)rand()/(double)RAND_MAX * (max - min) + min;
}

Solution 9 - C

double scale = 1.0 / ((double) RAND_MAX + 1.0);
int min, max;
...
rval = (int)(rand() * scale * (max - min + 1) + min);

Solution 10 - C

If you don't overly care about the 'randomness' of the low-order bits, just rand() % HI_VAL.

Also:

(double)rand() / (double)RAND_MAX;  // lazy way to get [0.0, 1.0)

Solution 11 - C

This answer does not focus on the randomness but on the arithmetic order. To get a number within a range, usually we can do it like this:

// the range is between [aMin, aMax]
double f = (double)rand() / RAND_MAX;
double result = aMin + f * (aMax - aMin);

However, there is a possibility that (aMax - aMin) overflows. E.g. aMax = 1, aMin = -DBL_MAX. A safer way is to write like this:

// the range is between [aMin, aMax]
double f = (double)rand() / RAND_MAX;
double result = aMin - f * aMin + f * aMax;

Based on this concept, something like this may cause a problem.

rand() % (max_number + 1 - minimum_number) + minimum_number
// 1. max_number + 1 might overflow
// 2. max_number + 1 - min_number might overflow

Solution 12 - C

if you care about the quality of your random numbers don't use rand()

use some other prng like http://en.wikipedia.org/wiki/Mersenne_twister or one of the other high quality prng's out there

then just go with the modulus.

Solution 13 - C

Just to add some extra detail to the existing answers.

The mod % operation will always perform a complete division and therefore yield a remainder less than the divisor.

> x % y = x - (y * floor((x/y)))

An example of a random range finding function with comments:

uint32_t rand_range(uint32_t n, uint32_t m) {
    // size of range, inclusive
    const uint32_t length_of_range = m - n + 1;

    // add n so that we don't return a number below our range
    return (uint32_t)(rand() % length_of_range + n);
}

Another interesting property as per the above: > x % y = x, if x < y

const uint32_t value = rand_range(1, RAND_MAX); // results in rand() % RAND_MAX + 1
// TRUE for all x = RAND_MAX, where x is the result of rand()
assert(value == RAND_MAX);
result of rand()

Solution 14 - C

2 cents (ok 4 cents):

n = rand()
x = result
l = limit

n/RAND_MAX = x/l

Refactor:

(l/1)*(n/RAND_MAX) = (x/l)*(l/1)

Gives:

x = l*n/RAND_MAX

int randn(int limit)

{

    return limit*rand()/RAND_MAX;

}

int i;

for (i = 0; i < 100; i++) { 

    printf("%d ", randn(10)); 
    if (!(i % 16)) printf("\n"); 

}

> test
0
5 1 8 5 4 3 8 8 7 1 8 7 5 3 0 0
3 1 1 9 4 1 0 0 3 5 5 6 6 1 6 4
3 0 6 7 8 5 3 8 7 9 9 5 1 4 2 8
2 7 8 9 9 6 3 2 2 8 0 3 0 6 0 0
9 2 2 5 6 8 7 4 2 7 4 4 9 7 1 5
3 7 6 5 3 1 2 4 8 5 9 7 3 1 6 4
0 6 5

Solution 15 - C

Just using rand() will give you same random numbers when running program multiple times. i.e. when you run your program first time it would produce random number x,y and z. If you run the program again then it will produce same x,y and z numbers as observed by me.

The solution I found to keep it unique every time is using srand()

Here is the additional code,

#include<stdlib.h>
#include<time.h>

time_t t;
srand((unsigned) time(&t));
int rand_number = rand() % (65 + 1 - 0) + 0 //i.e Random numbers in range 0-65.

To set range you can use formula : rand() % (max_number + 1 - minimum_number) + minimum_number

Hope it helps!

Solution 16 - C

I think the following does it semi right. It's been awhile since I've touched C. The idea is to use division since modulus doesn't always give random results. I added 1 to RAND_MAX since there are that many possible values coming from rand including 0. And since the range is also 0 inclusive, I added 1 there too. I think the math is arranged correctly avoid integer math problems.

#define MK_DIVISOR(max) ((int)((unsigned int)RAND_MAX+1/(max+1)))

num = rand()/MK_DIVISOR(65);

Solution 17 - C

You can change it by adding a % in front of the rand function in order to change to code

For example:

rand() % 50

will give you a random number in a range of 50. For you, replace 50 with 63 or 127

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionakwayView Question on Stackoverflow
Solution 1 - CTyler McHenryView Answer on Stackoverflow
Solution 2 - CfnurglewitzView Answer on Stackoverflow
Solution 3 - CVitim.usView Answer on Stackoverflow
Solution 4 - CBob KaufmanView Answer on Stackoverflow
Solution 5 - CMichael MyersView Answer on Stackoverflow
Solution 6 - CJoeyView Answer on Stackoverflow
Solution 7 - CReed CopseyView Answer on Stackoverflow
Solution 8 - CMark SynowiecView Answer on Stackoverflow
Solution 9 - CJohn BodeView Answer on Stackoverflow
Solution 10 - CgenpfaultView Answer on Stackoverflow
Solution 11 - CQQVEIView Answer on Stackoverflow
Solution 12 - CSpudd86View Answer on Stackoverflow
Solution 13 - CwulfgarproView Answer on Stackoverflow
Solution 14 - CScott FrancoView Answer on Stackoverflow
Solution 15 - CJay MehtaView Answer on Stackoverflow
Solution 16 - CView Answer on Stackoverflow
Solution 17 - CRoylatGnailView Answer on Stackoverflow