76
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?

jww
  • 97,681
  • 90
  • 411
  • 885
akway
  • 1,738
  • 4
  • 21
  • 20
  • 1
    Two things to remember here: 1. Never strip off the higher bits, since the lower ones are often less random. 2. Never use the system-provided rand() unless you don't really need good random numbers. – David Thornley Jul 29 '09 at 20:18
  • I will use a better RNG later, right now I am just toying around with generating random images. – akway Jul 29 '09 at 20:22
  • 1
    @David: you don't need to remember both those things, just the second. If you never use rand(), you don't have to worry about which bits in it are crappy in typical implementations. If you use a good RNG, then the low bits are just as good as the high ones. – Steve Jessop Jul 29 '09 at 23:06
  • Related: [How to generate a random int in C?](https://stackoverflow.com/q/822323/4561887). [Here is my answer there](https://stackoverflow.com/a/67746081/4561887), which contains the definition for my `int utils_rand(int min, int max)` func, which returns a random number using `rand()` which is in the specific range from `min` to `max`, inclusive, thereby also answering this question. I also scale to allow a case where `min` is `INT_MIN` and `max` is `INT_MAX`, which is normally not possible with `rand()` alone since it returns values from `0` to `RAND_MAX`, inclusive (1/2 that range). – Gabriel Staples May 31 '21 at 21:01

19 Answers19

102
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.

Silicomancer
  • 8,604
  • 10
  • 63
  • 130
Tyler McHenry
  • 74,820
  • 18
  • 121
  • 166
  • 2
    no, it's still number_of_numbers, but the number of numbers in the inclusive range 0-65 is 66 not 65. – Tyler McHenry Jul 29 '09 at 20:09
  • I think that said "rand() % 65 + 0" when I posted my comment. It looks right now. – Fred Larson Jul 29 '09 at 20:12
  • It did say that. I meant that I was mistaken about the number I wrote in the second code snippet, but not mistaken about the name I gave to the variable in the first code snippet. – Tyler McHenry Jul 29 '09 at 20:14
  • 6
    Modulo relies on the low-order bits which aren't as random as the high-order bits. Convert to float and multiply works better. – S.Lott Jul 29 '09 at 20:17
  • As I (and others) mentioned, there is a bias. But this bias is usually insignificant, especially if the range of numbers you are generating within is significantly smaller than RAND_MAX. – Tyler McHenry Jul 29 '09 at 20:20
  • Also, since RAND_MAX is almost definitely 2^n-1, if you are always looking for a range that is a power of two (as in both of the OPs examples), there is no bias at all. – Brian Postow Jul 29 '09 at 20:40
  • Unless the low-order bits are less random than the high-order bits. Then there would still be a bias (or perhaps a correlation), even when taking modulo a power of 2, by definition of "less random". – Steve Jessop Jul 29 '09 at 23:09
  • 2
    The low-order bits ARE less random. Further, the smaller the value of of `number_of_numbers`, the more apparent the bias is. Nothing to do with RAND_MAX. If `number_of_numbers` is 2, for example, you'll see the bias in the lowest-order bit. – S.Lott Jul 30 '09 at 12:07
  • @S.Lott: is `rand()` guaranteed by the standard to be implemented such that the low-order bits are less random, or is it merely convention? – Steve Jessop Jul 30 '09 at 15:55
  • Wait, so it's not that the lower order bits are less random because when you use mod, you end up with some remainder, and 0-R get an extra value going to them? The algorithm itself is more biased in thelower bits? You'd think that they could fix that by flipping the number before returning it or something... – Brian Postow Aug 04 '09 at 20:44
  • AFAIK rand() truncates the lowest bits on its own on some implementations, which results in RAND_MAX equal to 32K, which seems lowish. Anyway, if anyone ACTUALLY CARES about the randomness, they should use MT or something instead of rand() in the first place. – Kos Dec 20 '10 at 21:00
  • The subtracting of the zero makes the whole algorithm work. I see now. – annoying_squid Apr 01 '18 at 01:43
30

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

Vitim.us
  • 20,746
  • 15
  • 92
  • 109
22

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)
fnurglewitz
  • 2,097
  • 14
  • 21
  • 8
    You want one of those 1s to be 1.0 to ensure a float, otherwise you just get 0 + M... – Brian Postow Jul 29 '09 at 20:42
  • 3
    @BrianPostow No, you definitely do *not* want a floating point number there. The calculation is correct as it stands there and produces random numbers between `M` and `N` (inclusive). The distribution is quite uniform as long as `N-M` is small in comparison to `RAND_MAX`. Read the linked article. – Fritz Jun 17 '16 at 14:13
  • Did I mess up my implementation? Seems like this is very bad for my admittedly small test cases (implemented in `thirdRange()`). https://repl.it/@altendky/scaling-rand-can-cause-poor-distribution Does it have merit over the top rated answer in the limited cases of `N-M` small compared to `RAND_MAX`? – altendky Jan 22 '18 at 22:51
12

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

snipsnipsnip
  • 2,268
  • 2
  • 33
  • 34
Bob Kaufman
  • 12,864
  • 16
  • 78
  • 107
  • There *is* a better answer. I'm investigating now. I think that Mr. Atwood discussed this in Coding Horror a year or so back. – Bob Kaufman Jul 29 '09 at 20:14
  • @Sean: Store value of rand() in a temporary value. If it's high enough to have be in the error range, reroll. For the example mmyers gives, you would reroll if rand() is 3. – Brian Jul 29 '09 at 20:20
  • The better solution is if(rand() > .5) return 1; else return 0; – mox1 Jul 29 '09 at 23:11
  • A better solution is here: http://stackoverflow.com/questions/137783/given-a-function-which-produces-a-random-integer-in-the-range-1-to-5-write-a-fun. It was there the last time akway asked about random number generation, and it will still be there the next time someone asks this exact question or one which is mathematically equivalent ;-) – Steve Jessop Jul 29 '09 at 23:12
  • @James: that returns 1 with probability RAND_MAX/(RAND_MAX+1), and 0 with probability 1/(RAND_MAX+1). Not sure what that's supposed to achieve. – Steve Jessop Jul 29 '09 at 23:14
9

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.

snipsnipsnip
  • 2,268
  • 2
  • 33
  • 34
Michael Myers
  • 188,989
  • 46
  • 291
  • 292
7

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.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
7

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.

Joey
  • 344,408
  • 85
  • 689
  • 683
  • Sorry, misread; thought it said "using" Java'c java.util.Random, but you were just pointing out the method. Withdrawn :) – VeraKozya Feb 20 '18 at 23:01
  • 1
    This is a old answer so sorry to annoying you, still this answer is a bit strange as the question is taged with C, that would be good if you could take time to add an exemple of C equivalent code. For exemple, what is `next()` ? [here](https://rextester.com/ICTIC19273) a proposition that still need to replace `next()` by C equivalent function. – Stargateur Oct 10 '18 at 14:33
5

Updated to not use a #define

double RAND(double min, double max)
{
    return (double)rand()/(double)RAND_MAX * (max - min) + min;
}
Mark Synowiec
  • 5,385
  • 1
  • 22
  • 18
  • 2
    bad idea, due to all the caveats of macros. That macro fails in a number of cases because the arguments are not properly parenthesized, and even if you did do so properly, it would still evaluate the min argument twice, which would be bad if min were a function with side-effects. – Tyler McHenry Jul 29 '09 at 20:13
  • Lose the macro approach and convert to double. rand()/RAND_MAX is normally 0. – David Thornley Jul 29 '09 at 20:21
5
double scale = 1.0 / ((double) RAND_MAX + 1.0);
int min, max;
...
rval = (int)(rand() * scale * (max - min + 1) + min);
John Bode
  • 119,563
  • 19
  • 122
  • 198
3

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)
genpfault
  • 51,148
  • 11
  • 85
  • 139
  • So that would give either 0 or 1? Is there anyway I could chain that together and convert the resulting number from binary into decimal? That would add a lot of randomness... I think. – akway Jul 29 '09 at 20:09
  • @akway: No. The division gives a floating-point number between 0.0 and 1.0. `(int)(HI_VAL * ( (double)rand() / (double)RAND_MAX ))` generally does what you want. – S.Lott Jul 29 '09 at 20:16
  • 2
    Tip: Any time you do something to "add" randomness to a pseudo-random number generator, expect a high chance that you're inadvertently subtracting it...or at least not changing it. – Brian Jul 29 '09 at 20:17
  • (double)rand() / (double)RAND_MAX gives you a double between zero and one, not either 0 or 1. You can chain these, of sorts, but remember that not all generators work well that way. Some have dependencies between adjacent values. – David Thornley Jul 29 '09 at 20:18
  • Oh ok, that makes more sense. – akway Jul 29 '09 at 20:24
3

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
QQVEI
  • 49
  • 3
2

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.

Spudd86
  • 2,986
  • 22
  • 20
2

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()
wulfgarpro
  • 6,666
  • 12
  • 69
  • 110
2
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
Scott Franco
  • 481
  • 2
  • 15
2

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!

Jay Mehta
  • 1,511
  • 15
  • 20
1

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

RoylatGnail
  • 171
  • 1
  • 7
0

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);
0

Simpler alternative to @Joey's answer. If you decide to go with the % method, you need to do a reroll to get the correct distribution. However, you can skip rerolls most of the time because you only need to avoid numbers that fall in the last bucket:

int rand_less_than(int max) {
    int last_bucket_min = RAND_MAX - RAND_MAX % max;
    int value;
    do {
        value = rand();
    } while (last_bucket_min <= value);

    return value % max;
}

See @JarosrawPawlak's article for explanation with diagrams: Random number generator using modulo

In case of RAND_MAX < max, you need to expand the generator: Expand a random range from 1–5 to 1–7

snipsnipsnip
  • 2,268
  • 2
  • 33
  • 34
0
#include <stdio.h>
#include <stdlib.h>
#include <time.h>                           // this line is necessary

int main() {
    srand(time(NULL));                      // this line is necessary
    int random_number = rand() % 65;        // [0-64]

    return 0;
}

Foy any range between min_num and max_num:

int random_number = rand() % (max_num + 1 - min_num) + min_num;
Scott
  • 4,974
  • 6
  • 35
  • 62