Soru tam bir cevap için çok geniş, ancak birkaç ilginç noktayı seçmeme izin verin:
Neden "eşit derecede olası"
Her biri eşit olasılıkla 0, 1, ..., 10 sayılarını üreten basit bir rastgele sayı üreticiniz olduğunu varsayalım (bunu klasik olarak düşünün rand()
). Şimdi 0, 1, 2 aralığında her biri eşit olasılığa sahip rastgele bir sayı istiyorsunuz. Senin tepkisiz tepki almak olacaktır rand() % 3
. Ama bekleyin, kalan 0 ve 1, kalan 2'den daha sık meydana gelir, bu yüzden bu doğru değil!
Bu nedenle , tek tip rasgele tam sayıların kaynağını alan ve bunları örnekte olduğu gibi istediğimiz dağılıma dönüştüren düzgün dağılımlara ihtiyacımız var Uniform[0,2]
. Bunu iyi bir kütüphaneye bırakmak en iyisi!
Motorlar
Bu nedenle, tüm rasgeleliğin merkezinde, belirli bir aralıkta eşit olarak dağılan ve ideal olarak çok uzun bir periyodu olan bir sayı dizisi üreten iyi bir sözde rasgele sayı üreteci vardır. Standart uygulaması rand()
genellikle en iyisi değildir ve bu nedenle bir seçeneğe sahip olmak iyidir. Doğrusal-uyumlu ve Mersenne twister iki iyi seçenektir (LG aslında genellikle tarafından rand()
da kullanılır ); Yine, kütüphanenin bunu halletmesine izin vermek iyidir.
Nasıl çalışır
Kolay: önce bir motor kurun ve onu tohumlayın. Tohum, "rastgele" sayıların tüm dizisini tam olarak belirler, bu nedenle a /dev/urandom
) her seferinde farklı bir tane kullanın (örneğin, alınan ) ve b) bir rastgele seçimler dizisini yeniden oluşturmak istiyorsanız, tohumu saklayın.
#include <random>
typedef std::mt19937 MyRNG; // the Mersenne Twister with a popular choice of parameters
uint32_t seed_val; // populate somehow
MyRNG rng; // e.g. keep one global instance (per thread)
void initialize()
{
rng.seed(seed_val);
}
Şimdi dağıtımlar oluşturabiliriz:
std::uniform_int_distribution<uint32_t> uint_dist; // by default range [0, MAX]
std::uniform_int_distribution<uint32_t> uint_dist10(0,10); // range [0,10]
std::normal_distribution<double> normal_dist(mean, stddeviation); // N(mean, stddeviation)
... Ve motoru rastgele sayılar oluşturmak için kullanın!
while (true)
{
std::cout << uint_dist(rng) << " "
<< uint_dist10(rng) << " "
<< normal_dist(rng) << std::endl;
}
Eşzamanlılık
<random>
Geleneksel rand()
olanı tercih etmenin daha önemli bir nedeni de, artık rastgele sayı oluşturma iş parçacığının nasıl güvenli hale getirileceğinin çok açık ve açık olmasıdır: Ya her iş parçacığına kendi, iş parçacığı yerel motoru sağlayın, iş parçacığı yerel bir tohumda tohumlandı ya da erişimi senkronize edin motor nesnesine.
Çeşitli
- Bir ilginç bir yazı codeguru üzerinde TR1 Rastgele üzerinde.
- Wikipedia'nın iyi bir özeti var (teşekkürler, @Justin).
- Prensip olarak, her bir motor
result_type
, çekirdek için kullanılacak doğru integral türü olan a yazmalıdır. Ben için tohum zorlamak için beni zorladı kez bir arabası uygulanmasını olduğunu düşünüyorum std::mt19937
için uint32_t
x64 üzerinde, en sonunda bu sabit olmalıdır ve söyleyebileceğinizi MyRNG::result_type seed_val
ve böylece çok kolay değiştirilebilir motorunu yapmak.
rand
, bazı temel istatistik ve RNG kavramları için Wikipedia'ya hızlıca göz atmalısınız, aksi takdirde size<random>
çeşitli parçalarının mantığını ve kullanımını açıklamak gerçekten zor olacaktır .