Buscar..


Observaciones

Debido a los defectos de rand() , muchas otras implementaciones por defecto han surgido a lo largo de los años. Entre esos están:

Generación de números aleatorios básicos

La función rand() se puede usar para generar un valor entero pseudoaleatorio entre 0 y RAND_MAX ( 0 y RAND_MAX incluidos).

srand(int) se utiliza para inicializar el generador de números pseudoaleatorios. Cada vez que rand() se siembra con la misma semilla, debe producir la misma secuencia de valores. Solo se debe sembrar una vez antes de llamar a rand() . No se debe sembrar repetidamente ni volver a sembrar cada vez que desee generar un nuevo lote de números pseudoaleatorios.

La práctica estándar es usar el resultado del time(NULL) como semilla. Si su generador de números aleatorios requiere tener una secuencia determinista, puede inicializar el generador con el mismo valor en cada inicio de programa. Esto generalmente no es necesario para el código de la versión, pero es útil en las ejecuciones de depuración para hacer que los errores sean reproducibles.

Se recomienda sembrar siempre el generador, si no se siembra, se comporta como si se hubiera sembrado con srand(1) .

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

int main(void) {
    int i;
    srand(time(NULL));
    i = rand();

    printf("Random value between [0, %d]: %d\n", RAND_MAX, i);
    return 0;
}

Salida posible:

Random value between [0, 2147483647]: 823321433

Notas:

El estándar C no garantiza la calidad de la secuencia aleatoria producida. En el pasado, algunas implementaciones de rand() tenían serios problemas en la distribución y aleatoriedad de los números generados. El uso de rand() no se recomienda para necesidades serias de generación de números aleatorios, como la criptografía.

Generador Congruente Permutado

Aquí hay un generador de números aleatorios independiente que no se basa en rand() o funciones de biblioteca similares.

¿Por qué querrías tal cosa? Tal vez no confíe en el generador de números aleatorios integrado de su plataforma, o tal vez quiera una fuente reproducible de aleatoriedad independiente de cualquier implementación de biblioteca en particular.

Este código es PCG32 de pcg-random.org , un RNG moderno, rápido y de propósito general con excelentes propiedades estadísticas. No es criptográficamente seguro, así que no lo use para criptografía.

#include <stdint.h>

/* *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
 * Licensed under Apache License 2.0 (NO WARRANTY, etc. see website) */

typedef struct { uint64_t state;  uint64_t inc; } pcg32_random_t;

uint32_t pcg32_random_r(pcg32_random_t* rng) {
    uint64_t oldstate = rng->state;
    /* Advance internal state */
    rng->state = oldstate * 6364136223846793005ULL + (rng->inc | 1);
    /* Calculate output function (XSH RR), uses old state for max ILP */
    uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
    uint32_t rot = oldstate >> 59u;
    return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}

void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, uint64_t initseq) {
    rng->state = 0U;
    rng->inc = (initseq << 1u) | 1u;
    pcg32_random_r(rng);
    rng->state += initstate;
    pcg32_random_r(rng);
}

Y aquí está cómo llamarlo:

#include <stdio.h>
int main(void) {
    pcg32_random_t rng; /* RNG state */
    int i;

    /* Seed the RNG */
    pcg32_srandom_r(&rng, 42u, 54u);

    /* Print some random 32-bit integers */
    for (i = 0; i < 6; i++)
        printf("0x%08x\n", pcg32_random_r(&rng));
    
    return 0;
}

Restringir la generación a un rango dado

Por lo general, cuando se generan números aleatorios, es útil generar números enteros dentro de un rango, o un valor de p entre 0.0 y 1.0. Si bien la operación de módulo se puede usar para reducir la semilla a un entero bajo, este utiliza los bits bajos, que a menudo pasan por un ciclo corto, lo que resulta en una ligera desviación de la distribución si N es grande en proporción a RAND_MAX.

La macro

#define uniform() (rand() / (RAND_MAX + 1.0))

produce un valor de p de 0.0 a 1.0 - épsilon, por lo que

i = (int)(uniform() * N)

establecerá i en un número aleatorio uniforme dentro del rango de 0 a N - 1.

Desafortunadamente, hay una falla técnica, ya que se permite que RAND_MAX sea más grande de lo que una variable de tipo double puede representar con precisión. Esto significa que RAND_MAX + 1.0 evalúa como RAND_MAX y la función ocasionalmente devuelve la unidad. Sin embargo, esto es poco probable.

Generación Xorshift

Una alternativa buena y fácil a los procedimientos defectuosos de rand() es xorshift , una clase de generadores de números pseudoaleatorios descubiertos por George Marsaglia . El generador xorshift se encuentra entre los generadores de números aleatorios no criptográficos seguros más rápidos. Más información y otras implementaciones de ejemplo están disponibles en la página de Wikipedia de xorshift.

Ejemplo de implementación

#include <stdint.h>

/* These state variables must be initialised so that they are not all zero. */
uint32_t w, x, y, z;

uint32_t xorshift128(void) 
{
    uint32_t t = x;
    t ^= t << 11U;
    t ^= t >> 8U;
    x = y; y = z; z = w;
    w ^= w >> 19U;
    w ^= t;
    return w;
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow