¿Cómo generar un int aleatorio en C?

4 minutos de lectura

avatar de usuario
Kredns

¿Existe una función para generar un número int aleatorio en C? ¿O tendré que usar una biblioteca de terceros?

  • Ver también srand: por qué llamarlo sólo una vez.

    –Jonathan Leffler

    19 de febrero de 2015 a las 0:22

avatar de usuario
Laurence Gonsalves

Él rand() función en <stdlib.h> devuelve un entero pseudoaleatorio entre 0 y RAND_MAX. Puedes usar srand(unsigned int seed) para establecer una semilla.

Es una práctica común utilizar el % operador junto con rand() para obtener un rango diferente (aunque tenga en cuenta que esto altera un poco la uniformidad). Por ejemplo:

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

Si tu De Verdad Si te preocupas por la uniformidad, puedes hacer algo como esto:

/* Devuelve un entero en el rango [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;
  }
}

  • It is a common practice alright, but not the correct one. See this and this.

    – Lazer

    Aug 1, 2010 at 7:33


  • @Lazer: That’s why I said “though bear in mind that this throws off the uniformity somewhat”.

    – Laurence Gonsalves

    Aug 2, 2010 at 7:00

  • @AbhimanyuAryan The % is the modulus operator. It gives you the remainder of an integer division, so x % n will always give you a number between 0 and n - 1 (as long as x and n are both positive). If you still find that confusing, try writing a program that has i count from 0 to 100, and prints out i % n for some n of your choosing smaller than 100.

    – Laurence Gonsalves

    Aug 14, 2014 at 23:52

  • @necromancer I went ahead and added a perfectly uniform solution.

    – Laurence Gonsalves

    Aug 15, 2014 at 3:03

  • @Lazer the second link you posted is actually still not perfectly uniform. Casting to a double and back doesn’t help. The first link you posted has a perfectly uniform solution, though it will loop a lot for small upper bounds. I’ve added a perfectly uniform solution to this answer that shouldn’t loop as much even for small upper bounds.

    – Laurence Gonsalves

    Aug 15, 2014 at 3:31

  • should libsodium RNG be seeded before calling randombytes_buf?

    – user2199593

    Aug 29, 2017 at 10:32

  • Just call sodium_init() at some point. Don’t worry about the RNG, it uses the kernel’s.

    – Scott Arciszewski

    Aug 29, 2017 at 18:06

  • Note: I approved the recent edit for sodium_init() even though it’s not necessarily part of my example because it’s an important detail.

    – Scott Arciszewski

    Jul 18, 2018 at 14:28

  • Why is the use of OpenSSL and other userland PRNGs discouraged? The documentation for OpenSSL’s RAND_bytes() says it’s a cryptographically secure PRNG.

    – gsingh2011

    Jan 12, 2021 at 1:30

  • @gsingh2011 Read sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers

    – Scott Arciszewski

    Apr 19, 2021 at 3:18

Well, STL is C++, not C, so I don’t know what you want. If you want C, however, there is the rand() and srand() functions:

int rand(void);

void srand(unsigned seed);

These are both part of ANSI C. There is also the random() function:

long random(void);

But as far as I can tell, random() is not standard ANSI C. A third-party library may not be a bad idea, but it all depends on how random of a number you really need to generate.

user avatar
MH114

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.

user avatar
Yun

I had a serious issue with pseudo random number generator in my recent application: I repeatedly called my C program via a Python script and I was using as seed the following code:

srand(time(NULL))

However, since:

  • rand will generate the same pseudo random sequence give the same seed in srand (see man srand);
  • As already stated, time function changes only second from second: if your application is run multiple times within the same second, time will return the same value each time.

My program generated the same sequence of numbers.
You can do 3 things to solve this problem:

  1. mix time output with some other information changing on runs (in my application, the output name):

    srand(time(NULL) | getHashOfString(outputName))
    

    I used djb2 as my hash function.

  2. Increase time resolution. On my platform, clock_gettime was available, so I use it:

    #include<time.h>
    struct timespec nanos;
    clock_gettime(CLOCK_MONOTONIC, &nanos)
    srand(nanos.tv_nsec);
    
  3. Use both methods together:

    #include<time.h>
    struct timespec nanos;
    clock_gettime(CLOCK_MONOTONIC, &nanos)
    srand(nanos.tv_nsec | getHashOfString(outputName));
    

Option 3 ensures you (as far as I know) the best seed randomness, but it may create a difference only on very fast application.
In my opinion option 2 is a safe bet.

  • Even with these heuristics, don’t rely on rand() for cryptographic data.

    – domenukk

    Jul 26, 2019 at 16:03

  • rand() should not be used for cryptographic data, I agree. At least for me, my application didn’t involve cryptographic data, so for me it was ok the given method.

    – Koldar

    Jul 26, 2019 at 19:12

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad