C ++ 11'de rastgele sayı oluşturma: nasıl oluşturulur, nasıl çalışır? [kapalı]


102

Yakın zamanda C ++ 11'de rastgele sayılar üretmenin yeni bir yolunu buldum, ancak bu konuda okuduğum makaleleri sindiremedim (bu motor nedir, dağıtım gibi matematik terimi , "üretilen tüm tam sayıların eşit olasılıklı olduğu ").

Bu yüzden lütfen açıklayabilir

  • Onlar neler?
  • ne demek istiyorlar?
  • nasıl üretilir?
  • nasıl çalışırlar?
  • vb

Rastgele sayı oluşturma hakkında hepsini tek bir SSS'de arayabilirsiniz.


6
Dağıtımın ne olduğunu bilmeden RNG'ler hakkında soru sormak, bir ifadenin ne olduğunu bilmeden ifade ayrıştırıcıları hakkında soru sormak gibidir ... C ++ 11'deki RNG kütüphanesi, bazı istatistikleri bilen ve düz dağıtımın ürettiği düz dağıtımdan daha büyük ihtiyaçları olan kişilere yöneliktir. 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 .
Matteo Italia

26
@Matteo: Neredeyse. Bir çocuk, dağılımın ne olduğunu anlamadan bir kalıbın rastgele sayılar ürettiği kavramını kavrayabilir.
Benjamin Lindley

3
@Benjamin: İşte bu noktada onun anlayışı bitiyor, bu sadece ilk adım (motorlar) ve düz bir dağıtım oluşturmalarının neden önemli olduğunu bile anlamadan. Kütüphanenin geri kalanı, dağıtımları ve diğer istatistik kavramlarını anlamadan bir sır olarak kalır.
Matteo Italia

Yanıtlar:


142

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::mt19937için uint32_tx64 üzerinde, en sonunda bu sabit olmalıdır ve söyleyebileceğinizi MyRNG::result_type seed_valve böylece çok kolay değiştirilebilir motorunu yapmak.

Kerrek, üzerinde çalıştığım cevaptan çok daha iyi bir cevapla beni bir kez daha yumruk atıyor. +1
Justin ᚅᚔᚈᚄᚒᚔ

@Justin: Bir ton şeyi kaçırdığıma eminim, bu konuya daha fazla yön eklemekten çekinmeyin! :-)
Kerrek SB

13
"Bir şekilde nüfus edin" kısmı için, bence std::random_devicebundan daha çok bahsetmeye değer/dev/urandom
Cubbi

2
Bir örnek buradastd::random_device bulunabilir .
WKS

1
Wikipedia makalesindeki kod hatalı. rastgele ve rastgele2 aynıdır. Kod parçacığındaki yorumlardan yazarın <random> 'daki özelliklerin nasıl kullanılacağını anlamadığı açıktır.
user515430

3

Rastgele sayı üreteci, bir sayı verildiğinde size yeni bir sayı veren bir denklemdir. Tipik olarak ya ilk numarayı sağlarsınız ya da sistem zamanı gibi bir şeyden alınır.

Her yeni numara sorduğunuzda, denklemi yürütmek için önceki sayıyı kullanır.

Rastgele sayı üreteci, aynı sayıyı diğer sayılardan daha sık üretme eğilimindeyse, çok iyi kabul edilmez. yani, bir ile 5 arasında rastgele bir sayı istiyorsanız ve bu sayı dağılımına sahipseniz:

  • % 1: 1
  • 2:% 80
  • 3:% 5
  • 4:% 5
  • 5:% 9

2, diğer numaralardan daha sık üretilir, bu nedenle üretilmesi diğer sayılardan daha fazladır. Tüm sayılar eşit derecede olsaydı, her sayıyı her seferinde alma şansınız% 20 olurdu. Başka bir deyişle, yukarıdaki dağılım çok düzensizdir çünkü 2 tercih edilir. Tüm% 20'ler ile bir dağılım eşit olacaktır.

Tipik olarak, gerçek bir rastgele sayı istiyorsanız, verileri rastgele bir sayı oluşturucu yerine hava durumu veya başka bir doğal kaynaktan alırsınız.


8
Çoğu rastgele sayı üreteci iyi eşit dağılımlar üretir. Bunlar rastgele değiller; Sorun şu ki, bunlar hesaplanıyor ve böylece dizide yeterli sayı verilen bir sonraki sayıyı tahmin edebilirsiniz (bu gerçek, gerçekten rasgele sayıların gerekli olduğu güvenlik için onları kötü kılar). Oyunlar ve diğer şeyler için iyi olmalısın.
Martin York

5
Operatörün C ++ <random> başlığında sağlanan özellikler hakkında belirli bilgiler istediğinden oldukça eminim. Bu cevap, C ++ 'ı bir yana programlamayı bile ele almıyor.
Benjamin Lindley

1
@Martin: Güvenlik, gerçekten rastgele sayıların kaynağına ihtiyaç duymaz. Sayaç modunda (bir örnek için) AES, deterministik olmasına rağmen oldukça iyi iş çıkarabilir. Anahtarda makul miktarda entropi gerektirir, ancak gerçek bir rastgelelik gerektirmez.
Jerry Tabut

@Benjamin Lindley: Nevermind. Sadece tekrar oku ve yanıldığımı anladım.
N_A
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.