Seperti judulnya, saya mencoba untuk mencari tahu cara menghasilkan angka acak menggunakan C++11 <random>
perpustakaan. Saya telah mencoba dengan kode ini:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
Masalah dengan kode yang saya miliki adalah bahwa setiap kali saya mengkompilasi dan menjalankan, itu selalu menghasilkan angka yang sama. Jadi pertanyaan saya adalah apa fungsi lain di acak perpustakaan dapat mencapai hal ini ketika sedang benar-benar acak?
Untuk kasus penggunaan tertentu, saya mencoba untuk mendapatkan nilai dalam kisaran [1, 10]
Stephan T. Lavavej (stl) dari Microsoft melakukan pembicaraan di Akan Asli tentang cara menggunakan C++11 acak fungsi dan mengapa tidak menggunakan rand()
. Di dalamnya, ia termasuk slide yang pada dasarnya memecahkan pertanyaan anda. I've menyalin kode dari yang slide di bawah ini.
Anda dapat melihat-nya bicara penuh di sini: http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
#include <random>
#include <iostream>
int main() {
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<double> dist(1.0, 10.0);
for (int i=0; i<16; ++i)
std::cout << dist(mt) << "\n";
}
Kita menggunakan random_device
sekali untuk benih random number generator yang bernama mt
. random_device()
adalah lebih lambat dari mt19937
, tetapi hal itu tidak perlu menjadi unggulan karena permintaan data acak dari sistem operasi anda (yang akan sumber dari berbagai lokasi, seperti RdRand misalnya).
Melihat ini pertanyaan / jawaban, tampak bahwa uniform_real_distribution
mengembalikan nomor dalam kisaran [a, b)
, di mana anda ingin [a, b]
. Untuk melakukan itu, kami uniform_real_distibution
harus benar-benar terlihat seperti:
std::uniform_real_distribution<double> dist(1, std::nextafter(10, DBL_MAX));
Saya 'random' perpustakaan memberikan perangkat bungkus sekitar C++11 acak kelas. Anda dapat melakukan hampir semua hal dengan sederhana 'mendapatkan' metode.
Contoh:
auto val = Random::get(-10, 10); // bilangan Bulat auto val = Random::get(10.f, -10.f); // Float point
auto val = Random::dapatkan
auto val = Random::dapatkan( { 1, 3, 5, 7, 9 } ); // val = 1 atau 3 atau...
auto itu = Random::get( vec.begin(), vec.end() ); // ini = random iterator auto itu = Random::get( vec ); // return random iterator
Dan bahkan lebih hal-hal ! Check out halaman github:
Berikut ini's sesuatu yang saya hanya menulis sepanjang garis::
#include <random>
#include <chrono>
#include <thread>
using namespace std;
//==============================================================
// RANDOM BACKOFF TIME
//==============================================================
class backoff_time_t {
public:
random_device rd;
mt19937 mt;
uniform_real_distribution<double> dist;
backoff_time_t() : rd{}, mt{rd()}, dist{0.5, 1.5} {}
double rand() {
return dist(mt);
}
};
thread_local backoff_time_t backoff_time;
int main(int argc, char** argv) {
double x1 = backoff_time.rand();
double x2 = backoff_time.rand();
double x3 = backoff_time.rand();
double x4 = backoff_time.rand();
return 0;
}
~
Berikut ini adalah beberapa sumber daya anda dapat membaca tentang pseudo-random number generator.
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
Pada dasarnya, angka acak di komputer membutuhkan benih (nomor ini dapat menjadi waktu sistem saat ini).
Mengganti
std::default_random_engine generator;
Oleh
std::default_random_engine generator(<some seed number>);
Anda've punya dua situasi umum. Yang pertama adalah bahwa anda ingin angka acak dan tidak't terlalu sibuk tentang kualitas atau kecepatan eksekusi. Dalam hal ini, menggunakan makro berikut
#define uniform() (rand()/(RAND_MAX + 1.0))
yang memberikan p di kisaran 0 sampai 1 - epsilon (kecuali RAND_MAX lebih besar dari presisi ganda, tetapi khawatir tentang itu ketika anda datang untuk itu).
int x = (int) (seragam() * N);
Sekarang memberikan bilangan bulat acak pada 0 sampai N -1.
Jika anda perlu distro lain, anda harus mengubah p. Atau kadang-kadang itu's mudah untuk memanggil seragam() beberapa kali.
Jika anda ingin berulang perilaku, benih dengan konstan, jika benih dengan panggilan ke waktu().
Sekarang jika anda peduli tentang kualitas atau waktu menjalankan kinerja, ulang seragam(). Tapi kalau tidak,'t touch kode. Selalu menjaga seragam() 0 1 minus epsilon. Sekarang anda dapat membungkus C++ random number perpustakaan untuk membuat baik seragam(), tapi yang's semacam tingkat menengah pilihan. Jika anda peduli tentang karakteristik RNG, maka's juga bernilai investasi sedikit waktu untuk memahami bagaimana yang mendasari metode kerja, kemudian memberikan satu. Jadi anda've punya kontrol penuh dari kode, dan anda dapat menjamin bahwa dengan benih yang sama, urutan akan selalu persis sama, terlepas dari platform atau yang versi C++ anda terhubung ke.