수색…


비고

rand() 의 결함으로 인해 다른 많은 기본 구현이 수년에 걸쳐 나타났습니다. 그 중 :

기본 난수 생성

rand() 함수는 0RAND_MAX 사이의 의사 랜덤 정수 값을 생성하는 데 사용할 수 있습니다 ( 0RAND_MAX 포함).

srand(int) 는 의사 난수 생성 프로그램을 시드하는 데 사용됩니다. rand() 는 동일한 시드로 시드 될 때마다 동일한 값 시퀀스를 생성해야합니다. rand() 를 호출하기 전에 한 번만 시드해야합니다. 새 가상 배치를 생성 할 때마다 반복적으로 시드하거나 다시 시드하면 안됩니다.

표준적인 방법은 time(NULL) 의 결과 time(NULL) 를 시드로 사용하는 것입니다. 난수 생성기에 결정 성 순서가 필요한 경우 각 프로그램 시작시 동일한 값으로 생성기를 시드 할 수 있습니다. 일반적으로 릴리스 코드에는 필요하지 않지만 버그를 재현 할 수 있도록 디버그 실행에 유용합니다.

생성기를 시드하려면 시드를하지 않으면 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;
}

가능한 출력 :

Random value between [0, 2147483647]: 823321433

노트:

C 표준은 생성 된 무작위 순서의 품질을 보장하지 않습니다. 과거에는 rand() 의 일부 구현에서 생성 된 숫자의 분포와 임의성에 심각한 문제가있었습니다. rand() 의 사용은 암호화와 같이 심각한 난수 발생 요구에 대해서는 권장되지 않습니다.

허가 된 합동 생성기

다음은 rand() 또는 유사한 라이브러리 함수에 의존하지 않는 독립형 난수 생성기입니다.

왜 그렇게 원하는거야? 어쩌면 플랫폼의 내장 난수 생성기를 신뢰하지 않거나 특정 라이브러리 구현과 무관하게 임의성의 재현 가능한 소스를 원할 수도 있습니다.

이 코드는 pcg-random.org의 PCG32로 , 탁월한 통계적 특성을 지닌 현대적이고 빠른 범용 RNG입니다. 암호로 안전하지 않으므로 암호로 사용하지 마십시오.

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

다음과 같이 호출하는 방법입니다.

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

주어진 범위로 생성 제한

일반적으로 난수를 생성 할 때 범위 내에서 정수를 생성하거나 0.0과 1.0 사이의 p 값을 생성하는 것이 좋습니다. 모듈러스 연산을 사용하여 시드를 낮은 정수로 줄일 수는 있지만 N은 RAND_MAX에 비례하여 커지면 약간의 사이클을 거치는 작은 비트를 사용합니다.

매크로

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

0.0 ~ 1.0의 ρ 값을 생성합니다 - 엡실론이므로

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

i 를 0 ~ N - 1 범위의 균일 한 난수로 설정합니다.

불행히도 RAND_MAX가 double 타입의 변수보다 더 크게 허용된다는 기술적 결함이 있습니다. 이것은 RAND_MAX + 1.0RAND_MAX + 1.0 평가되고 함수가 때때로 단일을 반환한다는 것을 의미합니다. 그러나 이것은있을 법하지 않습니다.

Xorshift 세대

결함있는 rand() 프로 시저에 대한 좋은 대안은 xorshift 이며 George Marsaglia가 발견 한 의사 난수 생성기 클래스입니다. xorshift 생성기는 가장 빠른 비 암호화 보안 난수 생성기 중 하나입니다. 자세한 정보 및 기타 예제 구현은 xorshift Wikipedia 페이지 에서 사용할 수 있습니다.

구현 예

#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
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow