Vấn đề nào tốt hơn cho PCG.SE so với việc triển khai PCG, Trình tạo số ngẫu nhiên tốt hơn ? Bài báo mới này tuyên bố sẽ trình bày một trình tạo số ngẫu nhiên nhanh, khó dự đoán, nhỏ, tối ưu về mặt thống kê.
Việc thực hiện C tối thiểu của nó chỉ là khoảng chín dòng:
// *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));
}
(từ: http://www.pcg-random.org/doad.html )
Câu hỏi là: bạn có thể làm tốt hơn không?
Quy tắc
Viết chương trình hoặc xác định hàm thực hiện PCG trên các số nguyên không dấu 32 bit. Điều này khá rộng: bạn có thể in ra một chuỗi vô hạn, xác định pcg32_random_r
hàm và cấu trúc tương ứng, v.v.
Bạn phải có khả năng khởi tạo trình tạo số ngẫu nhiên tương đương với hàm C sau:
// 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);
}
(từ pcg_basic.c:37
:)
Gọi trình tạo số ngẫu nhiên mà không cần gieo hạt trước là hành vi không xác định.
Để dễ dàng kiểm tra trình của bạn, hãy xác minh rằng, khi được gieo bằng initstate = 42
và initseq = 52
, đầu ra là 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
Chấm điểm
Điểm chuẩn. Đo bằng byte. Thấp nhất là tốt nhất. Trong trường hợp hòa, nộp trước đó thắng. Tiêu chuẩn áp dụng.
Giải pháp mẫu
Biên dịch gcc -W -Wall
sạch sẽ (phiên bản 4.8.2).
So sánh trình của bạn với điều này để đảm bảo bạn nhận được cùng một trình tự.
#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;
}
Trình tự:
2380307335
948027835
187788573
3952545547
2315139320
3279422313
2401519167
2248674523
3148099331
3383824018
2720691756
2668542805
2457340157
3945009091
1614694131
4292140870