Rastgele Sayı Gerçekten Rastgele Mi ?

Rastgele Sayı Gerçekten Rastgele Mi ?

Rastgele Sayı Gerçekten Rastgele Mi ?

  6 dakika Okuma Süresi
Diyelim ki bir proje yapıyorsunuz ve size rastgele sayılar lazım, ne yapardınız ? Aslında birçok dilde rastgele sayı üretmeye yarayan random sınıfları bulunmakta. Peki bu random sınıfları rastgele sayıyı nasıl belirliyor ? Çünkü bilgisayarlar günümüzde rastgele bir sayı üretebilme yeteneğine sahip değil. E bilgisayarın böyle bir yeteneği yoksa nasıl yapıyor bu işi ?
Bilgisayarı geçelim, siz nasıl yapardınız ? Şahsen ben amele gibi uğraşır rastgele aklımdan sayılar oluşturur ve bir listeye eklerdim. Her rastgele sayı istendiğinde de o listeden sırayla sayı verirdim. Gerçekten amele gibi değil mi ? :)
Yada bunun yanında öyle bir şey bulmalıyız ki sürekli değişsin ve o şeyi bir fonksiyona sokup değişik değişik şeyler yapıp kullanıcıya vermekte mantıklı olabilir.
Aslında bu ikinci bahsettiğim şey bizim bildiğimiz random sınıflarının yaptığı şey, örneğin C#'taki Random sınıfının yeni bir nesnesini türettiğinizde sınıf içerisindeki constructor metod o anki geçerli saati alıyor ve bi hash fonksiyonundan geçirdikten sonra çıkan sonucu rastgele sayı olarak sunuyor.
Fakat örneğin

for(int i = 0; i < 100; i++)
    Console.WriteLine(new Random().Next());
kodunu çalıştırdığınızda
699648196
699648196
699648196
699648196
161004551
931532479
931532479
931532479
931532479
931532479
931532479
931532479
931532479
931532479
931532479
931532479
931532479
931532479
931532479
580160588
şeklinde giden bir çıktı göreceksiniz. Tabiki birebir aynı çıktıyı almayacaksınız, zaten bunun önemi yok fakat 15-20 tane aynı sayıyı çıktı alacaksınız. Yani 100 tane rastgele sayı istiyorsanız 5-6 tane farklı sayı alacaksınız, gerisi tekrar olacaktır.
Peki bunun nedeni nedir ? Şudur; Random sınıfı oluşturulduğunda constructor metod geçerli zamanı alıyor dedik ama bunu 100 kere hele de for gibi zamandan daha hızlı olan bir şey ile yaptığınızda çok kısa bir zaman değişikliği olacağından tekrar eden çıktılar alacaksınız.
E bunu nasıl düzelteceğiz derseniz;

Random random = new Random();
for(int i = 0; i < 100; i++)
    Console.WriteLine(random.Next());
kod yapısını kullanmanız gerekiyor.
Bu kodda ise for'un dışında Random nesnesi oluşturduğumuz için zamanı bir kere almış ve Next() fonksiyonu ile rastgele sayı üreten fonksiyonu 100 kere çağırdığımız için 100 farklı rastgele sayı göreceğiz.
1882812320
1693951941
1743175736
336804405
1302249091
1472110336
270883127
143958040
974421327
653414200
1343749561
758594862
Son yazdığımız kodun ekran çıktısı böyle devam edecek ve farkettiyseniz tekrar eden sayı yok.
Fakat bu kodda Random nesnesi oluştururken örneğin 1234 gibi bir parametre gönderirsek aynı sorunu yine yaşayacağız.
E tekrar etmeyen rastgele sayı oluşturamaz mıyız ? Cevap: Evet oluşturabiliriz. Peki nasıl ?
Bi tane dizi yada liste oluşturayım, rastgele sayı üreteyim ve liste içerisinde o sayının olup olmadığına bakayım, liste içinde yoksa ekleyeyim. Kulağa çok mantıklı geliyor ve hatta kafasına yatanlar da vardır illa ki. Hatta denemek isteyenler için şuraya bi kod bırakıyorum;

List<int> RastgeleSayiUret(int adet, int baslangic, int bitis)
{
    List<int> sayilar = new List<int>();
    Random rnd = new Random();
    for(int i = 0;i < adet; i++)
    {
        int rastgele = rnd.Next(baslangic, bitis);
        if(!sayilar.Contains(rastgele))
            sayilar.Add(rastgele);
    }
    return sayilar;
}

Aslında evet çok mantıklı görünüyor ama 10 sayı için yaptık, 1000 sayı için yaptık ama 1 000 000 sayı üreteceksek akşama kadar bekleriz, bekle babam yaz gelsin :)
E o zaman nasıl hızlandıracağız bunu ? Tabiki listelerden daha performanslı olan HashSet sınıfını kullanarak. Hem kod açısından hem de performans açısından HashSet kullanmak daha iyi olacaktır. Onun kodunu da şöyle bırakayım;

List<int> RastgeleSayiUret(int adet, int baslangic, int bitis)
{
    var sayilar = new HashSet<int>();
    Random rnd = new Random();
    for(int i = 0; i < adet; i++)
        sayilar.Add(rnd.Next(baslangic, bitis);
    return sayilar.ToList();
}
Her iki fonksiyon yapısını da incelediğimizde HashSet kullanmak hem daha az kod yazmamıza sebep oldu, hem de daha performanslı oldu.
Performans farkını farketmek istiyorsanız her iki fonksiyonu da yazıp çalıştırın ve görün :) Göreceksiniz ki HashSet kullandığımız fonksiyon süre ve performans olarak daha iyi sonuçlar verecektir.

Evet bi söyleşimizin daha sonuna geldik, biraz uzun bi yazı oldu ama adı üstünde söyleşi :) Herkese hayırlı günler diliyorum.


  • İçeriği Paylaş:

İÇERİĞİ DEĞERLENDİR

Toplam Değerlendirme Sayısı: 0
Toplam Değerlendirme: 0 / 5

Cevap Yaz