İlişkin rand() % n
ideale daha az olması
Yapmanın rand() % n
homojen olmayan bir dağılımı vardır. Değerlerin sayısı 20'nin katı olmadığından orantısız sayıda belirli değer elde edersiniz
Daha sonra rand()
, tipik olarak doğrusal bir konjügasyon jeneratörüdür ( diğerleri vardır , sadece bu büyük olasılıkla uygulanır - ideal parametrelerden daha azı ile (parametreleri seçmenin birçok yolu vardır). Bununla ilgili en büyük sorun, genellikle içindeki düşük bitlerin (bir % 20
tür ifadesiyle elde ettikleriniz ) o kadar rasgele olmamasıdır. Bir tane hatırlamak rand()
gelen dönüşümlü düşük bit nerede yıl önce 1
için 0
yapılan her çağrı ile rand()
çok tesadüfi değildi -.
Gönderen Rand (3) kılavuz sayfasında:
Linux C Library'deki rand () ve srand () sürümleri aynı
rastgele () ve srandom () gibi rasgele sayı üreteci, bu yüzden alt sıra
bitler yüksek dereceli bitler kadar rastgele olmalıdır. Ancak, daha eski
rand () uygulamaları ve farklı
sistemleri, düşük mertebeden bitler yüksek mertebeden çok daha az rastgele
sipariş bitleri. Bu işlevi olması amaçlanan uygulamalarda kullanmayın
iyi rasgelelik gerektiğinde taşınabilir.
Bu artık tarihe düşmüş olabilir, ancak yığının herhangi bir yerinde saklanan hala kötü bir rand () uygulamasına sahip olmanız mümkündür. Bu durumda, hala oldukça uygulanabilir.
Yapılacak şey aslında iyi bir rasgele sayı kütüphanesi (iyi rasgele sayılar verir) kullanmak ve daha sonra istediğiniz aralıkta rasgele sayılar istemektir.
İyi bir rastgele sayı biti kodu örneği (bağlantılı videoda 13: 00'dan itibaren)
#include <iostream>
#include <random>
int main() {
std::mt19937 mt(1729); // yes, this is a fixed seed
std::uniform_int_distribution<int> dist(0, 99);
for (int i = 0; i < 10000; i++) {
std::cout << dist(mt) << " ";
}
std::cout << std::endl;
}
Bunu şununla karşılaştır:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL));
for (int i = 0; i < 10000; i++) {
printf("%d ", rand() % 100);
}
printf("\n");
}
Bu programların her ikisini de çalıştırın ve bu çıktıda belirli sayıların ne sıklıkta ortaya çıktığını (veya çıkmadığını) karşılaştırın.
İlgili video: rand () zararlı olarak kabul edildi
Rand () 'ın Nethack'ta kendi uygulamalarında izlemesi ve göz önünde bulundurması gereken hatalara neden olan bazı tarihsel yönleri:
Nethack RNG Sorunu
Rand (), Nethack'ın rasgele sayı üretimi için çok temel bir işlevdir. Nethack'in kullandığı yol buggy veya lrand48 () 'nin crappy sözde rasgele sayılar ürettiği iddia edilebilir. (Ancak, lrand48 (), tanımlı bir PRNG yöntemi kullanan bir kitaplık işlevidir ve bunu kullanan herhangi bir program, bu yöntemin zayıflıklarını dikkate almalıdır.)
Hata, Nethack'ın (bazen sadece rn (2) durumunda olduğu gibi) lrand48 () 'in sonuçlarının alt bitlerine dayanmasıdır. Bu nedenle, tüm oyundaki RNG kötü çalışıyor. Bu, özellikle kullanıcı eylemleri daha fazla rasgele ortaya çıkmadan önce, yani karakter oluşturma ve birinci seviye oluşturmada fark edilir.
Yukarıdakiler 2003'teyken, amaçlanan oyununuzu çalıştıran tüm sistemlerin iyi bir rand () işlevine sahip güncel bir Linux sistemi olacağı düşünülmeyebilir.
Bunu sadece kendiniz için yapıyorsanız, bazı kod yazıp çıkışı ent ile test ederek rastgele sayı üretecinizin ne kadar iyi olduğunu test edebilirsiniz .
Rasgele sayıların özellikleri hakkında
'Rasgele' nin tam olarak rasgele olmayan başka yorumları da vardır. Rasgele bir veri akışında, aynı sayıyı iki kez elde etmek oldukça mümkündür. Bir bozuk para (rastgele) çevirirseniz, arka arkaya iki kafa almak oldukça mümkündür. Ya da iki kez bir zar atın ve aynı sayıyı arka arkaya iki kez alın. Ya da bir rulet tekerleğini döndürmek ve orada aynı sayıyı iki kez almak.
Sayıların dağılımı
Bir şarkı listesi çalarken, insanlar 'rastgele'nin aynı şarkının veya sanatçının arka arkaya ikinci kez çalınmayacağı anlamına gelmesini bekler. Bir çalma listesi olarak kabul edilir arka arkaya iki kez Beatles oynamak Having (olsa 'rastgele değil' olduğu rastgele). Dört şarkının çalma listesinin toplam sekiz kez çalındığı algısı:
1 3 2 4 1 2 4 3
şundan daha 'rastgele':
1 3 3 2 1 4 4 2
Şarkıların 'karıştırılması' için daha fazlası: Şarkıları karıştırmak nasıl?
Tekrarlanan değerlerde
Değerleri tekrarlamak istemiyorsanız, dikkate alınması gereken farklı bir yaklaşım vardır. Olası tüm değerleri oluşturun ve karıştırın.
Eğer rand()
(veya başka herhangi bir rastgele sayı üreteci) arıyorsanız, onu yedek ile çağırıyorsunuz. Aynı numarayı her zaman iki kez alabilirsiniz. Seçeneklerden biri, gereksinimlerinizi karşılayana kadar değerleri tekrar tekrar atmaktır. Bunun belirleyici olmayan bir çalışma süresine sahip olduğunu ve daha karmaşık bir geri izleme yapmaya başlamadığınız sürece kendinizi sonsuz bir döngü olduğu bir durumda bulabileceğinizi göstereceğim.
Liste ve Seçim
Diğer bir seçenek, olası tüm geçerli durumların bir listesini oluşturmak ve ardından bu listeden rastgele bir öğe seçmektir. Odadaki tüm boş noktaları (bazı kurallara uyan) bulun ve ardından bu listeden rastgele bir nokta seçin. Ve sonra bitene kadar tekrar tekrar yapın.
Karıştır
Diğer yaklaşım sanki bir kart destesi gibi karıştırmaktır. Odadaki tüm boş noktalar ile başlayın ve ardından her bir kurala / sürece boş noktaları dağıtarak bunları boş bir noktaya atayarak başlayın. Kartınız bittiğinde işiniz bittiğinde veya kart istemeyi bıraktığınız zaman.