Misalkan Anda ingin menggunakan <random>
fasilitas C ++ dalam program praktis (untuk beberapa definisi "praktis" - kendala di sini adalah bagian dari pertanyaan ini). Anda memiliki kode yang kira-kira seperti ini:
int main(int argc, char **argv) {
int seed = get_user_provided_seed_value(argc, argv);
if (seed == 0) seed = std::random_device()();
ENGINE g(seed); // TODO: proper seeding?
go_on_and_use(g);
}
Pertanyaan saya adalah, untuk tipe apa Anda harus menggunakannya ENGINE
?
Saya dulu selalu mengatakan
std::mt19937
karena itu cepat untuk mengetik dan memiliki pengenalan nama. Tapi hari ini sepertinya semua orang mengatakan bahwa Mersenne Twister sangat berat dan tidak bersahabat dan bahkan tidak lulus semua tes statistik yang dilakukan orang lain.Saya ingin mengatakan
std::default_random_engine
karena ini adalah "standar" yang jelas. Tetapi saya tidak tahu apakah itu bervariasi dari satu platform ke platform lainnya, dan saya tidak tahu apakah ini baik secara statistik.Karena semua orang ada di platform 64-bit hari ini, haruskah kita setidaknya menggunakan
std::mt19937_64
lebihstd::mt19937
?Saya ingin mengatakan
pcg64
atauxoroshiro128
karena mereka tampaknya dihormati dan ringan, tetapi mereka tidak ada<random>
sama sekali.Aku tidak tahu apa-apa tentang
minstd_rand
,minstd_rand0
,ranlux24
,knuth_b
, dll - pasti mereka harus baik untuk sesuatu?
Jelas ada beberapa kendala yang bersaing di sini.
Kekuatan mesin. (
<random>
tidak memiliki PRNG yang kuat secara kriptografis, tetapi masih, beberapa yang terstandarisasi "lebih lemah" daripada yang lain, kan?)sizeof
mesin.Kecepatannya
operator()
.Kemudahan penyemaian.
mt19937
sangat sulit untuk diunggulkan dengan benar karena memiliki begitu banyak kondisi untuk diinisialisasi.Portabilitas antara vendor perpustakaan. Jika satu vendor
foo_engine
menghasilkan angka yang berbeda dari vendor lainfoo_engine
, itu tidak baik untuk beberapa aplikasi. (Semoga ini tidak mengesampingkan apa pun kecuali mungkindefault_random_engine
.)
Menimbang semua kendala ini sebaik mungkin, apa yang akan Anda katakan adalah jawaban "praktik terbaik yang ada di perpustakaan"? Haruskah saya terus menggunakan std::mt19937
, atau apa?
Jawaban:
Referensi C ++ daftar semua mesin acak yang saat ini disediakan oleh C ++. Namun, pemilihan mesin meninggalkan banyak hal yang diinginkan (misalnya, lihat daftar saya generator acak berkualitas tinggi ). Contohnya:
default_random_engine
didefinisikan-implementasi, jadi tidak diketahui apakah mesin memiliki kelemahan statistik yang mungkin diperhatikan oleh aplikasi.linear_congruential_engine
mengimplementasikan generator linier kongruensial. Namun, mereka cenderung memiliki kualitas yang buruk kecuali modulusnya prima dan sangat besar (setidaknya 64 bit). Juga, mereka tidak bisa menerima lebih banyak biji daripada modulus mereka.minstd_rand0
danminstd_rand
hanya mengakui sekitar 2 ^ 31 biji.knuth_b
membungkusminstd_rand0
dan melakukan shuffle Bays-Durham itu.mt19937
danmt19937_64
bisa menerima lebih banyak benih jika mereka diinisialisasi lebih baik (misalnya, dengan menginisialisasistd::seed_seq
dengan beberapa outputrandom_device
, bukan hanya satu), tetapi mereka menggunakan sekitar 2500 byte negara.ranlux24
danranlux48
menggunakan sekitar 577 bit state tetapi mereka lambat (mereka bekerja dengan menyimpan beberapa dan membuang output pseudorandom lainnya).Namun, C ++ juga memiliki dua mesin yang membungkus mesin lain untuk berpotensi meningkatkan sifat keacakannya:
discard_block_engine
membuang beberapa output dari mesin acak yang diberikan.shuffle_order_engine
mengimplementasikan pengocokan Bays – Durham dari mesin acak yang diberikan.Sebagai contoh, mungkin, katakanlah, untuk memiliki shuffle Bays-Durham
mt19937
,ranlux24
, atau kustomlinear_congruential_engine
denganshuffle_order_engine
. Mungkin mesin yang dibungkus lebih berkualitas daripada yang asli. Namun, sulit untuk memprediksi kualitas statistik mesin baru tanpa mengujinya .Jadi, sambil menunggu tes seperti itu, tampaknya itu
mt19937
adalah mesin paling praktis dalam standar C ++ untuk saat ini. Saya menyadari, bagaimanapun, dari setidaknya satu proposal untuk menambahkan mesin angka acak lain untuk versi C ++ di masa depan (lihat kertas C ++ P2075 ).sumber
Menurut C ++ Reference ,
default_random_engine
:Jadi untuk penggunaan ringan Anda tidak perlu khawatir tentang apa pun, benih
default_random_engine
denganEpoch Time (time(0))
dan itu akan cukup baik;)sumber