더 나은 난수 생성기 인 PCG 를 구현하는 것보다 PCG.SE의 더 나은 문제는 무엇입니까 ? 이 새로운 논문 은 빠르고 예측하기 어려운 작고 통계적으로 최적 인 난수 생성기를 제시한다고 주장합니다.
최소 C 구현은 약 9 줄입니다.
// *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));
}
( 출처 : http://www.pcg-random.org/download.html )
문제는 : 더 잘할 수 있습니까?
규칙
32 비트 부호없는 정수에서 PCG를 구현하는 프로그램을 작성하거나 함수를 정의하십시오. 이것은 매우 광범위합니다. 무한 시퀀스를 출력하고 pcg32_random_r
함수와 해당 구조체를 정의 할 수 있습니다 .
다음 C 함수와 동일하게 난수 생성기를 시드 할 수 있어야합니다.
// pcg32_srandom(initstate, initseq)
// pcg32_srandom_r(rng, initstate, initseq):
// Seed the rng. Specified in two parts, state initializer and a
// sequence selection constant (a.k.a. stream id)
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);
}
(에서 : pcg_basic.c:37
)
먼저 시드하지 않고 난수 생성기를 호출하는 것은 정의되지 않은 동작입니다.
제출 내용을 쉽게 확인하려면 initstate = 42
and로 시드 할 때 initseq = 52
출력이 2380307335
다음 과 같은지 확인하십시오 .
$ tail -n 8 pcg.c
int main()
{
pcg32_random_t pcg;
pcg32_srandom_r(&pcg, 42u, 52u);
printf("%u\n", pcg32_random_r(&pcg));
return 0;
}
$ gcc pcg.c
$ ./a.out
2380307335
채점
표준 점수. 바이트 단위로 측정됩니다. 최저가 최고입니다. 동점 인 경우, 조기 제출이 이깁니다. 표준 허점이 적용됩니다.
샘플 솔루션
gcc -W -Wall
깨끗하게 컴파일합니다 (버전 4.8.2).
제출 내용을 이것과 비교하여 동일한 순서를 얻으십시오.
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
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);
}
int main()
{
size_t i;
pcg32_random_t pcg;
pcg32_srandom_r(&pcg, 42u, 52u);
for (i = 0; i < 16; i++)
{
printf("%u\n", pcg32_random_r(&pcg));
}
return 0;
}
순서:
2380307335
948027835
187788573
3952545547
2315139320
3279422313
2401519167
2248674523
3148099331
3383824018
2720691756
2668542805
2457340157
3945009091
1614694131
4292140870