March 04, 2013

Merhaba,

Yaklaşık 1,5 haftadır, projeyi kısmen rafa kaldırmıştım ve haftasonu (yani dün, pazar günü) yeniden başladım. Rafdan indirdim demiyorum çünkü önemli sayfaları kafamda uçuşuyorlardı...:)

Neyse, şimdi bitirdim ama henüz yeni bir başlık açıp nakletmeden evvel iyice test etmeliyim. O zamana kadar, hemen test kodlarını vermeliyim. Bunu öylesine çok yapmak istiyorum ki "işte D'nin gücü" dermişcesine, bu büyük mutluluğu armağan etmeyi arzuluyorum:

 union parçala {
   ulong data;
   ubyte[8] p8b;
   ushort[4] p4s;
   uint[2] p2i;
 }

 struct Tx {
   parçala veri;
   size_t dizin;

   TypeInfo tür = typeid(ulong); // fixed a

   this(T)(T değeri) {
     this.dizin = 1;  // artık ilk eleman 1...:)
     this.veri = parçala(
             cast(ulong)değeri);
     this.tür = typeid(T); // boş kurulmamalı (a)
   }

   void popFront() {
     dizin = empty() ? 0 : dizin + 1;
   }

   @property
   bool empty() const {
     return (dizin > tür.tsize());
   }

   @property
   ulong front() const {
     return dizin ? part(dizin) : veri.data;
   }

   @property
   ubyte part(size_t i) const
   in { assert(i, "0 alamaz!"); } body {
     return i > tür.tsize() ? 0 : veri.p8b[i - 1];
   }

   T to(T)() {
     switch(T.sizeof) {
       case 1: return cast(T)veri.p8b[0];
       case 2: return cast(T)veri.p4s[0];
       case 4: return cast(T)veri.p2i[0];
       default:
     }
     return cast(T)veri.data;
   }
 }

import std.stdio, std.conv, std.random;

char rasgeleSeç(string seçenekler) {
 auto rasgeleSayı = uniform(0, size_t.max);
 auto aralıkOranı = size_t.max / seçenekler.length;
 size_t biriniSeç = rasgeleSayı / aralıkOranı;

 return seçenekler[biriniSeç];
}

auto rasgeleTür(size_t adedi) {
 Tx[] sonuç;

 while(adedi--) {
   final switch(rasgeleSeç("LISB10")) {
     case 'L': ulong s7 = uniform(ulong.min, ulong.max);
               sonuç ~= Tx(s7); break;
     case 'I': uint s5 = uniform(uint.min, uint.max);
               sonuç ~= Tx(s5); break;
     case 'S': ushort s3 = uniform(ushort.min, ushort.max);
               sonuç ~= Tx(s3); break;
     case 'B': ubyte s1 = uniform(ubyte.min, ubyte.max);
               sonuç ~= Tx(s1); break;
     case '1': sonuç ~= Tx(true); break;
     case '0': sonuç ~= Tx(false);
   }
 }
 return sonuç;
}

void main() {
   auto test = rasgeleTür(10);

   foreach(t; test) {
       //t.veri.data.writeln(": ", t.tür);/*
       size_t adedi = t.tür is typeid(bool) ? 1 : t.tür.tsize() * 8;
       string düzen = "%." ~ to!string(adedi) ~ "b";
       writefln(düzen, t.veri.data);//*/
   }
}

'Son bir söz:' Bu basit, rasgele veri türü seçen ve bunun içini yine rasgele veriler ile dolduran kodları C'de yapamazsınız demeyeceğim ama zorlanacağınız aşikar! Çünkü aynı dizi içinde farklı veri yapılarını başka bir yere aktarabiliyor, bunları istediğiniz esneklikte ekrana yazabiliyor ve/veya kullanabiliyorsunuz.

Alıntı (Örnek bir ekran çıktı...):

>

'0011101101011110010011010110000010011111100000100011010110000010
0
1
0
0
1101111111100101100100010100001000111101110010100110011011010111
1101101111010111
10000010
1011110100001111
1'

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 04, 2013

Alıntı (acehreli):

>

Alıntı (Salih Dinçer):

>
> >       dizin = empty() ? 0 : dizin + 1;
> > ```

>
> Orada herhalde '==' olmalı.
Burada amacım dizin sınıra eriştiyse başa dönmesini (0 olmasını) sağlamak değilse kendisini bir arttırmak. Bir nevi dizin.max'ı belirleyebildiğim işaretsiz bir tür gibi. Sınırına geldiğinde başa sarıyor...

Alıntı (acehreli):
>
>
>

char rasgeleSeç(string seçenekler) {
auto rasgeleSayı = uniform(0, size_t.max);
auto aralıkOranı = size_t.max / seçenekler.length;
size_t biriniSeç = rasgeleSayı / aralıkOranı;

return seçenekler[biriniSeç];
}

>

Uzun yoldan yapmışsın çünkü uniform zaten eşit dağılımlı rasgele sayılar üretir (adı üstünde). :)

> char rasgeleSeç(string seçenekler) {
>     return seçenekler[uniform(0 .. $)];
> }
> ```

Bu yöntemi bilmiyordum ama sanırım şu şekilde ''seçenekler[uniform(0, $)];'' arada virgül olacak değil mi? Yine de uniform'a çok güvenmiyorum. Ardı ardına daha çok benzer seçim yapacakmış gibi geliyor bana. O yüzde algoritmanın frekansını size_t.max'a kadar yükselttim ya; yine de denemeli.

Alıntı (acehreli):
>
> ... bilmiyorum senin için önemli mi ama seçenekler arasında bulunmayan bir indeks döndürme tehliken de var.
>
> Bunun etkisini görmek için şöyle değerler uyduralım: size_t.max 100 olsun; seçenekler.length de 3... Bu durumda aralıkOranı==33 olur. uniform 99 döndürmüşse bu işlev 99/33 sonucunda 3 döndürür. O da seçenekler'in yasal bir indeksi değil.
Sanırım 32bit ve 64bit sistemlerde size_t.max çok büyük bir sayı olacağı için ve seçenekler de bu sayının yanında çok küçük kalacağından böyle bir tehlike görünmüyor. Tabi yukarıdaki kolay yöntem gibi her ikisini de denemek lazım. Örneğin 1 milyar seçim arasında seçeneklerini dağılım oranına basit bir eşleme tablosu ile bakılabilir.

Katkılar için teşekkür ederim...

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
March 04, 2013

Denedim sanki fark yok gibi, herhalde Ali hocamın ki daha hızlı olsa gerek:

import std.stdio, std.random;

char r1() {
   string seçenekler = "ABC";
   auto rasgeleSayı = uniform(0, size_t.max);
   auto aralıkOranı = size_t.max / seçenekler.length;
   size_t biriniSeç = rasgeleSayı / aralıkOranı;

   return seçenekler[biriniSeç];
}

char r2() {
   string seçenekler = "ABC";
   return seçenekler[uniform(0, $)];
}

void main() {
 int[char] R1 = [ 'A': 0, 'B': 0, 'C': 0 ];
 int[char] R2 = [ 'A': 0, 'B': 0, 'C': 0 ];

 size_t adedi = 1000_000_000;
 while(adedi--) {
   R1[r1]++;
   R2[r2]++;
 }
 R1.writeln(": uzun");
 R2.writeln(": kısa");
}/* Çıktısı:
['A':333347757, 'B':333326399, 'C':333325844]: uzun
['A':333334064, 'B':333331179, 'C':333334757]: kısa
*/

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 04, 2013

Alıntı (Salih Dinçer):

>
>       dizin = empty() ? 0 : dizin + 1;
> ```


Orada herhalde '==' olmalı.

Alıntı:
>
>

char rasgeleSeç(string seçenekler) {
auto rasgeleSayı = uniform(0, size_t.max);
auto aralıkOranı = size_t.max / seçenekler.length;
size_t biriniSeç = rasgeleSayı / aralıkOranı;

return seçenekler[biriniSeç];
}

Uzun yoldan yapmışsın çünkü uniform zaten eşit dağılımlı rasgele sayılar üretir (adı üstünde). :)

char rasgeleSeç(string seçenekler) {
   return seçenekler[uniform(0 .. $)];
}

Tekrar hatırlatma: string'i bayt deposu olarak kullanmış oluyoruz. Umarız birisi bu işlevi rasgele harf amacıyla çağırmaz çünkü ancak bir UTF-8 kod birimi seçme amacıyla kullanılabiliyor.

Üstelik, bilmiyorum senin için önemli mi ama seçenekler arasında bulunmayan bir indeks döndürme tehliken de var.

Bunun etkisini görmek için şöyle değerler uyduralım: size_t.max 100 olsun; seçenekler.length de 3... Bu durumda aralıkOranı==33 olur. uniform 99 döndürmüşse bu işlev 99/33 sonucunda 3 döndürür. O da seçenekler'in yasal bir indeksi değil.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 04, 2013

Ali hocam bu haklısın çünkü seçenek sayısı arttıkça tehlike artıyormuş...

Bu durumda zaten daha hızlı olan diğer kolay yöntemi kullanacağımdan, programın test sırasında çökme ihtimali ortadan kalkıyor. İşte böyle rasgele durumlarda emin olmak için ne yapmak gerekiyor bilmiyorum. Ya matematiğin kuvvetli olmalı ya da tüm olasılıkları test eden bir döngü icra etmeli.

Bu 2. ihtimal kuşkusuz çok vakit alacak!

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 04, 2013

Alıntı (Salih Dinçer):

>

Burada amacım dizin sınıra eriştiyse başa dönmesini (0 olmasını) sağlamak değilse kendisini bir arttırmak. Bir nevi dizin.max'ı belirleyebildiğim işaretsiz bir tür gibi. Sınırına geldiğinde başa sarıyor...

Ben de amacının o olduğunu farketmiştim ama if deyimlerinde bazen == yerine = kullanılmasına benzeyen hataya düştüğünü sanmıştım. Değilmiş tabii ki çünkü = işlecinin önceliği üçlü işleçten daha düşük. Ben bu gibi yanılgılar nedeniyle gereksiz ;) parantezler kullanmayı seviyorum:

     dizin = (empty() ? 0 : dizin + 1);

Alıntı:

>

sanırım şu şekilde ''seçenekler[uniform(0, $)];'' arada virgül olacak değil mi?

Doğru. :blush:

Alıntı:

>

Sanırım 32bit ve 64bit sistemlerde size_t.max çok büyük bir sayı olacağı için ve seçenekler de bu sayının yanında çok küçük kalacağından böyle bir tehlike görünmüyor.

Hayır, tehlike geçerli. uniform'un size_t.max-1 döndürdüğünü varsayalım (bu örnekte -5'e kadar aynı durum var):

import std.stdio;

void main()
{
   char[] seçenekler;
   seçenekler.length = 10;

   auto rasgeleSayı = (size_t.max - 1); // uniform(0, size_t.max);
   writeln("rasgeleSayı: ", rasgeleSayı);
   auto aralıkOranı = size_t.max / seçenekler.length;
   writeln("aralıkOranı: ", aralıkOranı);
   size_t biriniSeç = rasgeleSayı / aralıkOranı;
   writeln("biriniSeç: ", biriniSeç);
}

Çıktısı:
'
rasgeleSayı: 18446744073709551614
aralıkOranı: 1844674407370955161
biriniSeç: 10
'
Seçilen indeks 10 elemanlı dizi için yasal değil.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

1 2
Next ›   Last »