Sepertinya saya melihat banyak jawaban di mana seseorang menyarankan penggunaan <random>
untuk menghasilkan angka acak, biasanya bersama dengan kode seperti ini:
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 5);
dis(gen);
Biasanya ini menggantikan beberapa jenis "kekejian yang tidak suci" seperti:
srand(time(NULL));
rand()%6;
Kita mungkin mengkritik cara lama dengan alasan yang time(NULL)
memberikan entropi rendah, time(NULL)
dapat diprediksi, dan hasil akhirnya tidak seragam.
Tapi semua itu benar dengan cara baru: hanya memiliki lapisan yang lebih berkilau.
rd()
mengembalikan satuunsigned int
. Ini memiliki setidaknya 16 bit dan mungkin 32. Itu tidak cukup untuk menyemai kondisi 19937 bit MT.Menggunakan
std::mt19937 gen(rd());gen()
(seeding dengan 32 bit dan melihat keluaran pertama) tidak memberikan distribusi keluaran yang baik. 7 dan 13 tidak pernah bisa menjadi keluaran pertama. Dua biji menghasilkan 0. Dua belas biji menghasilkan 1226181350. ( Link )std::random_device
dapat, dan terkadang, diimplementasikan sebagai PRNG sederhana dengan benih tetap. Oleh karena itu, mungkin menghasilkan urutan yang sama di setiap proses. ( Link ) Ini bahkan lebih buruk daritime(NULL)
.
Lebih buruk lagi, sangat mudah untuk menyalin dan menempelkan potongan kode sebelumnya, terlepas dari masalah yang dikandungnya. Beberapa solusi untuk ini memerlukan memperoleh largish perpustakaan yang mungkin tidak cocok untuk semua orang.
Sehubungan dengan hal ini, pertanyaan saya adalah Bagaimana cara menyemai mt19937 PRNG secara ringkas, portabel, dan menyeluruh dalam C ++?
Mengingat masalah di atas, jawaban yang bagus:
- Harus sepenuhnya menyemai mt19937 / mt19937_64.
- Tidak bisa hanya mengandalkan
std::random_device
atautime(NULL)
sebagai sumber entropi. - Sebaiknya tidak mengandalkan Boost atau libaries lainnya.
- Harus muat dalam sejumlah kecil baris sehingga akan terlihat bagus saat disalin ke dalam jawaban.
Pikiran
Pemikiran saya saat ini adalah bahwa keluaran dari
std::random_device
dapat dihaluskan (mungkin melalui XOR) dengantime(NULL)
, nilai yang berasal dari pengacakan ruang alamat , dan konstanta hard-code (yang dapat diatur selama distribusi) untuk mendapatkan bidikan upaya terbaik di entropi.std::random_device::entropy()
tidak memberikan indikasi yang baik tentang apa yangstd::random_device
mungkin dilakukan atau tidak dilakukan.
std::random_device
,, time(NULL)
dan alamat fungsi, kemudian di-XOR bersama-sama untuk menghasilkan semacam sumber entropi dengan upaya terbaik.
std::random_device
dengan benar pada platform yang Anda rencanakan untuk menjalankan program Anda, dan menyediakan fungsi pembantu yang membuat generator unggulan ( seed11::make_seeded<std::mt19937>()
)