Sök…


Anmärkningar

På grund av bristerna i rand() har många andra standardimplementeringar dykt upp under åren. Bland dessa är:

Grundläggande slumpnummergenerering

Funktionen rand() kan användas för att generera ett pseudo-slumpmässigt heltal mellan 0 och RAND_MAX ( 0 och RAND_MAX inkluderat).

srand(int) används för att fröa den pseudo-slumpmässiga talgeneratorn. Varje gång rand() ympas med samma utsäde, måste det producera samma sekvens av värden. Det bör bara fröas en gång innan du ringer rand() . Det bör inte utsättas för flera gånger eller återinsättas varje gång du vill generera ett nytt parti pseudo-slumpmässiga nummer.

Standardpraxis är att använda tidsresultatet time(NULL) som frö. Om din slumptalsgenerator kräver att ha en deterministisk sekvens kan du fröa generatorn med samma värde på varje programstart. Detta krävs vanligtvis inte för release-kod, men är användbart i felsökningskurser för att göra buggar reproducerbara.

Det rekommenderas att alltid fröa generatoren, om den inte utsädes, den uppträder som om den sådd med 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;
}

Möjlig utgång:

Random value between [0, 2147483647]: 823321433

Anmärkningar:

C-standarden garanterar inte kvaliteten på den producerade slumpmässiga sekvensen. Tidigare hade vissa implementeringar av rand() allvarliga problem i fördelning och slumpmässighet av de genererade siffrorna. Användning av rand() rekommenderas inte för allvarliga behov av slumpmässigt antal, till exempel kryptografi.

Tillåtna Congruential Generator

Här är en fristående slumptalsgenerator som inte litar på rand() eller liknande biblioteksfunktioner.

Varför skulle du vilja ha något sådant? Du kanske inte litar på din plattforms inbyggda slumptalsgenerator, eller kanske du vill ha en reproducerbar källa för slumpmässighet oberoende av någon specifik biblioteksimplementering.

Denna kod är PCG32 från pcg-random.org , ett modernt, snabbt allmänt RNG med utmärkta statistiska egenskaper. Det är inte kryptografiskt säkert, så använd det inte för kryptografi.

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

Så här kallar du det:

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

Begränsa generationen till ett visst intervall

Vanligtvis vid generering av slumpmässiga nummer är det användbart att generera heltal inom ett intervall, eller ett ap-värde mellan 0,0 och 1,0. Även om moduloperation kan användas för att reducera fröet till ett lågt heltal använder de låga bitarna, som ofta går igenom en kort cykel, vilket resulterar i en liten spridning av fördelningen om N är stor i proportion till RAND_MAX.

Makro

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

producerar ap-värde på 0,0 till 1,0 - epsilon, så

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

kommer att sätta i till ett enhetligt slumpmässigt nummer inom intervallet 0 till N - 1.

Tyvärr finns det en teknisk brist, eftersom RAND_MAX tillåts vara större än en variabel av typen double exakt kan representera. Detta betyder att RAND_MAX + 1.0 utvärderar till RAND_MAX och funktionen ibland ger enhet. Detta är dock osannolikt.

Xorshift Generation

Ett bra och enkelt alternativ till de felaktiga förfarandena i rand() är xorshift , en klass av pseudo-slumpmässigt antal generatorer som upptäckts av George Marsaglia . Xorshift-generatorn är en av de snabbaste icke-kryptografiskt säkra slumptalsgeneratorerna. Mer information och andra exempel på implementering finns på xorshift Wikipedia-sidan

Exempel implementering

#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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow