within - random() in c




How to generate a random int in C? (16)

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


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: You might prefer to use random and srandom.


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:

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.


C Program to generate random number between 9 and 50

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

int main()
{
    srand(time(NULL));
    int lowerLimit = 10, upperLimit = 50;
    int r =  lowerLimit + rand() % (upperLimit - lowerLimit);
    printf("%d", r);
}

In general we can generate a random number between lowerLimit and upperLimit-1

i.e lowerLimit is inclusive or say r ∈ [ lowerLimit, upperLimit )


Despite all the people suggestion rand() here, you don't want to use rand() unless you have to! The random numbers that rand() produces are often very bad. To quote from the Linux man page:

The versions of rand() and srand() in the Linux C Library use the same random number generator as random(3) and srandom(3), so the lower-order bits should be as random as the higher-order bits. However, on older rand() implementations, and on current implementations on different systems, the lower-order bits are much less random than the higher-order bits. Do not use this function in applications intended to be portable when good randomness is needed. (Use random(3) instead.)

Regarding portability, random() is also defined by the POSIX standard for quite some time now. rand() is older, it appeared already in the first POSIX.1 spec (IEEE Std 1003.1-1988), whereas random() first appeared in POSIX.1-2001 (IEEE Std 1003.1-2001), yet the current POSIX standard is already POSIX.1-2008 (IEEE Std 1003.1-2008), which received an update just a year ago (IEEE Std 1003.1-2008, 2016 Edition). So I would consider random() to be very portable.

POSIX.1-2001 also introduced the lrand48() and mrand48() functions, see here:

This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.

And pretty good pseudo random source is the arc4random() function that is available on many systems. Not part of any official standard, appeared in BSD around 1997 but you can find it on systems like Linux and macOS/iOS.


Have a look at ISAAC (Indirection, Shift, Accumulate, Add, and Count). Its uniformly distributed and has an average cycle length of 2^8295.


Hearing a good explanation of why using rand() to produce uniformly distributed random numbers in a given range is a bad idea, I decided to take a look at how skewed the output actually is. My test case was fair dice throwing. Here's the C code:

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

int main(int argc, char *argv[])
{
    int i;
    int dice[6];

    for (i = 0; i < 6; i++) 
      dice[i] = 0;
    srand(time(NULL));

    const int TOTAL = 10000000;
    for (i = 0; i < TOTAL; i++)
      dice[(rand() % 6)] += 1;

    double pers = 0.0, tpers = 0.0;
    for (i = 0; i < 6; i++) {
      pers = (dice[i] * 100.0) / TOTAL;
      printf("\t%1d  %5.2f%%\n", dice[i], pers);
      tpers += pers;
    }
    printf("\ttotal:  %6.2f%%\n", tpers);
}

and here's its output:

 $ gcc -o t3 t3.c
 $ ./t3 
        1666598  16.67%     
        1668630  16.69%
        1667682  16.68%
        1666049  16.66%
        1665948  16.66%
        1665093  16.65%
        total:  100.00%
 $ ./t3     
        1667634  16.68%
        1665914  16.66%
        1665542  16.66%
        1667828  16.68%
        1663649  16.64%
        1669433  16.69%
        total:  100.00%

I don't know how uniform you need your random numbers to be, but the above appears uniform enough for most needs.

Edit: it would be a good idea to initialize the PRNG with something better than time(NULL).


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.


If your system supports the arc4random family of functions I would recommend using those instead the standard rand function.

The arc4random family includes:

uint32_t arc4random(void)
void arc4random_buf(void *buf, size_t bytes)
uint32_t arc4random_uniform(uint32_t limit)
void arc4random_stir(void)
void arc4random_addrandom(unsigned char *dat, int datlen)

arc4random returns a random 32-bit unsigned integer.

arc4random_buf puts random content in it's parameter buf : void *. The amount of content is determined by the bytes : size_t parameter.

arc4random_uniform returns a random 32-bit unsigned integer which follows the rule: 0 <= arc4random_uniform(limit) < limit, where limit is also an unsigned 32-bit integer.

arc4random_stir reads data from /dev/urandom and passes the data to arc4random_addrandom to additionally randomize it's internal random number pool.

arc4random_addrandom is used by arc4random_stir to populate it's internal random number pool according to the data passed to it.

If you do not have these functions, but you are on Unix, then you can use this code:

/* This is C, not C++ */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h> /* exit */
#include <stdio.h> /* printf */

int urandom_fd = -2;

void urandom_init() {
  urandom_fd = open("/dev/urandom", O_RDONLY);

  if (urandom_fd == -1) {
    int errsv = urandom_fd;
    printf("Error opening [/dev/urandom]: %i\n", errsv);
    exit(1);
  }
}

unsigned long urandom() {
  unsigned long buf_impl;
  unsigned long *buf = &buf_impl;

  if (urandom_fd == -2) {
    urandom_init();
  }

  /* Read 4 bytes, or 32 bits into *buf, which points to buf_impl */
  read(urandom_fd, buf, sizeof(long));
  return buf_impl;
}

The urandom_init function opens the /dev/urandom device, and puts the file descriptor in urandom_fd.

The urandom function is basically the same as a call to rand, except more secure, and it returns a long (easily changeable).

However, /dev/urandom can be a little slow, so it is recommended that you use it as a seed for a different random number generator.

If your system does not have a /dev/urandom, but does have a /dev/random or similar file, then you can simply change the path passed to open in urandom_init. The calls and APIs used in urandom_init and urandom are (I believe) POSIX-compliant, and as such, should work on most, if not all POSIX compliant systems.

Notes: A read from /dev/urandom will NOT block if there is insufficient entropy available, so values generated under such circumstances may be cryptographically insecure. If you are worried about that, then use /dev/random, which will always block if there is insufficient entropy.

If you are on another system(i.e. Windows), then use rand or some internal Windows specific platform-dependent non-portable API.

Wrapper function for urandom, rand, or arc4random calls:

#define RAND_IMPL /* urandom(see large code block) | rand | arc4random */

int myRandom(int bottom, int top){
    return (RAND_IMPL() % (top - bottom)) + bottom;
}

My minimalistic solution should work for random numbers in range [min, max). Use srand(time(NULL)) before invoking the function.

int range_rand(int min_num, int max_num) {
    if (min_num >= max_num) {
        fprintf(stderr, "min_num is greater or equal than max_num!\n"); 
    }
    return min_num + (rand() % (max_num - min_num));
} 

On modern x86_64 CPUs you can use the hardware random number generator via _rdrand64_step()

Example code:

#include <immintrin.h>

uint64_t randVal;
if(!_rdrand64_step(&randVal)) {
  // Report an error here: random number generation has failed!
}
// If no error occured, randVal contains a random 64-bit number

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;
  }
}

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:


This is hopefully a bit more random than just using srand(time(NULL)).

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

int main(int argc, char **argv)
{
    srand((unsigned int)**main + (unsigned int)&argc + (unsigned int)time(NULL));
    srand(rand());

    for (int i = 0; i < 10; i++)
        printf("%d\n", rand());
}

Try this, I put it together from some of the concepts already referenced above:

/*    
Uses the srand() function to seed the random number generator based on time value,
then returns an integer in the range 1 to max. Call this with random(n) where n is an integer, and you get an integer as a return value.
 */

int random(int max) {
    srand((unsigned) time(NULL));
    return (rand() % max) + 1;
}

You want to use rand(). Note (VERY IMPORTANT): make sure to set the seed for the rand function. If you do not, your random numbers are not truly random. This is very, very, very important. Thankfully, you can usually use some combination of the system ticks timer and the date to get a good seed.


#include <stdio.h>
#include <dos.h>

int random(int range);

int main(void)
{
    printf("%d", random(10));
    return 0;
}

int random(int range)
{
    struct time t;
    int r;

    gettime(&t);
    r = t.ti_sec % range;
    return r;
}




random