# How to generate a random int in C?

## How to generate a random int in C?

### Question

Is there a function to generate a random int number in C? Or will I have to use a third party library?

### Accepted Answer

Note: Don't use`rand()`

for security. If you need a cryptographically secure number, see this answer instead.

```
#include <time.h>
#include <stdlib.h>
srand(time(NULL)); // Initialization, should only be called once.
int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX.
```

*Edit*: On Linux, you might prefer to use random and srandom.

Read more... Read less...

The `rand()`

function in `<stdlib.h>`

returns a pseudo-random integer between 0 and `RAND_MAX`

. You can use `srand(unsigned int seed)`

to set a seed.

It's common practice to use the `%`

operator in conjunction with `rand()`

to get a different range (though bear in mind that this throws off the uniformity somewhat). For example:

```
/* random int between 0 and 19 */
int r = rand() % 20;
```

If you *really* care about uniformity you can do something like this:

```
/* Returns an integer in the range [0, n).
*
* Uses rand(), and so is affected-by/affects the same seed.
*/
int randint(int n) {
if ((n - 1) == RAND_MAX) {
return rand();
} else {
// Supporting larger values for n would requires an even more
// elaborate implementation that combines multiple calls to rand()
assert (n <= RAND_MAX)
// Chop off all of the values that would cause skew...
int end = RAND_MAX / n; // truncate skew
assert (end > 0);
end *= n;
// ... and ignore results from rand() that fall above that limit.
// (Worst case the loop condition should succeed 50% of the time,
// so we can expect to bail out of this loop pretty quickly.)
int r;
while ((r = rand()) >= end);
return r % n;
}
}
```

### If you need secure random characters or integers:

As addressed in how to safely generate random numbers in various programming languages, you'll want to do one of the following:

- Use libsodium's
`randombytes`

API - Re-implement what you need from libsodium's sysrandom implementation yourself, very carefully
- More broadly, use
`/dev/urandom`

, not`/dev/random`

. Not OpenSSL (or other userspace PRNGs).

For example:

```
#include "sodium.h"
int foo()
{
char myString[32];
uint32_t myInt;
if (sodium_init() < 0) {
/* panic! the library couldn't be initialized, it is not safe to use */
return 1;
}
/* myString will be an array of 32 random bytes, not null-terminated */
randombytes_buf(myString, 32);
/* myInt will be a random number between 0 and 9 */
myInt = randombytes_uniform(10);
}
```

`randombytes_uniform()`

is cryptographically secure and unbiased.

Lets go through this. First we use the srand() function to seed the randomizer. Basically, the computer can generate random numbers based on the number that is fed to srand(). If you gave the same seed value, then the same random numbers would be generated every time.

Therefore, we have to seed the randomizer with a value that is always changing. We do this by feeding it the value of the current time with the time() function.

Now, when we call rand(), a new random number will be produced every time.

```
#include <stdio.h>
int random_number(int min_num, int max_num);
int main(void)
{
printf("Min : 1 Max : 40 %d\n", random_number(1,40));
printf("Min : 100 Max : 1000 %d\n",random_number(100,1000));
return 0;
}
int random_number(int min_num, int max_num)
{
int result = 0, low_num = 0, hi_num = 0;
if (min_num < max_num)
{
low_num = min_num;
hi_num = max_num + 1; // include max_num in output
} else {
low_num = max_num + 1; // include max_num in output
hi_num = min_num;
}
srand(time(NULL));
result = (rand() % (hi_num - low_num)) + low_num;
return result;
}
```

If you need better quality pseudo random numbers than what `stdlib`

provides, check out **Mersenne Twister**. It's faster, too. Sample implementations are plentiful, for example here.

The standard C function is `rand()`

. It's good enough to deal cards for solitaire, but it's awful. Many implementations of `rand()`

cycle through a short list of numbers, and the low bits have shorter cycles. The way that some programs call `rand()`

is awful, and calculating a good seed to pass to `srand()`

is hard.

The best way to generate random numbers in C is to use a third-party library like OpenSSL. For example,

```
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rand.h>
/* Random integer in [0, limit) */
unsigned int random_uint(unsigned int limit) {
union {
unsigned int i;
unsigned char c[sizeof(unsigned int)];
} u;
do {
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
} while (u.i < (-limit % limit)); /* u.i < (2**size % limit) */
return u.i % limit;
}
/* Random double in [0.0, 1.0) */
double random_double() {
union {
uint64_t i;
unsigned char c[sizeof(uint64_t)];
} u;
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
/* 53 bits / 2**53 */
return (u.i >> 11) * (1.0/9007199254740992.0);
}
int main() {
printf("Dice: %d\n", (int)(random_uint(6) + 1));
printf("Double: %f\n", random_double());
return 0;
}
```

Why so much code? Other languages like Java and Ruby have functions for random integers or floats. OpenSSL only gives random bytes, so I try to mimic how Java or Ruby would transform them into integers or floats.

For integers, we want to avoid *modulo bias*. Suppose that we got some random 4 digit integers from `rand() % 10000`

, but `rand()`

can only return 0 to 32767 (as it does in Microsoft Windows). Each number from 0 to 2767 would appear more often than each number from 2768 to 9999. To remove the bias, we can retry `rand()`

while the value is below 2768, because the 30000 values from 2768 to 32767 map uniformly onto the 10000 values from 0 to 9999.

For floats, we want 53 random bits, because a `double`

holds 53 bits of precision (assuming it's an IEEE double). If we use more than 53 bits, we get rounding bias. Some programmers write code like `rand() / (double)RAND_MAX`

, but `rand()`

might return only 31 bits, or only 15 bits in Windows.

OpenSSL's `RAND_bytes()`

seeds itself, perhaps by reading `/dev/urandom`

in Linux. If we need many random numbers, it would be too slow to read them all from `/dev/urandom`

, because they must be copied from the kernel. It is faster to allow OpenSSL to generate more random numbers from a seed.

More about random numbers:

- Perl's Perl_seed() is an example of how to calculate a seed in C for
`srand()`

. It mixes bits from the current time, the process ID, and some pointers, if it can't read`/dev/urandom`

. - OpenBSD's arc4random_uniform() explains modulo bias.
- Java API for java.util.Random describes algorithms for removing bias from random integers, and packing 53 bits into random floats.