October 11, 2012

Minik notlar:

  1. k ve j'yi for döngüleri içinde tanımlamanı öneririm.

  2. delegate içinde bulunduğu kapsamı gösteren gösterge de barındırdığından normalde function'dan daha ağır bir olanak olarak kabul edilir.

Senin durumunda yalnızca birincisi function'a dönüştürülebiliyor çünkü diğer ikisi birinciyi kullanıyorlar. Dikkat edersen, bitMask bir işlev değil, bir temsilci nesnesi. Dolayısıyla diğer ikisi bu yerel nesneye eriştikleri için delegate olmak zorundalar:

   ubyte function (uint) bitMask = (k) => cast(ubyte)1 << ((k % 16) >> 1);
   bool delegate (uint) bitTest = (k) => (veri[k >> 4] & bitMask(k)) == 0;
   void delegate (uint) bitSet = (k) { veri[k >> 4] |= bitMask(k); };

Sanırım normal işlev kullanırsan kod daha hafif hale gelir. (Her zaman olduğu gibi: Bunlar hep tahmin, ölçmeden emin olamayız.)

   ubyte bitMask (uint k) { return cast(ubyte)1 << ((k % 16) >> 1); }
   bool bitTest (uint k) { return (veri[k >> 4] & bitMask(k)) == 0; }
   void bitSet (uint k) { veri[k >> 4] |= bitMask(k); }
  1. %d int içindir. Tam doğru olması için ya %u olmalı ya da en iyisi %s olarak bırakmalı.

Ali

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

October 11, 2012

Teşekkürler hocam, aralıkları da katıp algoritmayı daha lezzetli hale getirebilseydik çok iyi olurdu. Ancak ben de denediğimde kaçırdığı asal olmayan tek sayılar çıkıyor. Aslında ikinci döngüde parantezin dışında +1 yapmak yerine içinde yani şöyle (xAsal+2) / k yapmak veya daha fazla arttırmak netice veriyor. Sorunun kaynağı ise küsüratlı işlemlerin aşağıya yuvarlanmasından kaynaklanıyor. Ne hikmetse olayı tek bir eşittir ile çözebiliyoruz...:)

Bu arada bahsettiğiniz geliştirmeyi ben daha önce, oranı döngü dışında hesaplatarak denemiştim. Aradaki fark o kadar küçük ki 50 milyon asal sayı için 1 saniyenin altında diyebilirim. Belki çok çok büyük sayılarda (öyle ya sayı büyüdükçe artmalı!) daha büyük gecikmeler olacaktır. Ancak oraya kadar hafıza yetmediği için ulong sınırlarına henüz gelemiyorum...:(

Şimdi bir düşüncemi sizlerle paylaşmak isterim. Belki bunu yapabilirsek ulong sınırına kadar asal sayıları üretebiliriz...

Nasıl olsa biz ikinci döngünün hemen altında xSay ve k.write("\t") ile asal sayıları sayıp ekrana yazabiliyoruz. Öyleyse geride kalan bitleri data = data[1..$] diliminde yaptığımız gibi silebiliriz. Tabi bunu öyle bir zamanda yapmalıyız ki (çünkü her byte 16 tek sayıyı üzerinde barındırıyor!) yanlışlıkla işler karışmasın...:)

Sanırım bunu henüz denemesem de Eratosten sınıfındaki 'bitSet()' işlevinde yapabiliriz; 16 sayısını gözardı etmeden...

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

October 11, 2012

Bir şey daha:

for döngüsünün denetim bölümü her döngüde işletilmek zorundadır. Normald (xAsal / k) bölme işlemi yavaşlık katıyor olabilir. Tabii derleyici, ne xAsal'ın ne de k'nin döngü içinde veya çağrılan işlevler içinde değiştirilmediklerini kanıtlayabilirse o zaman hesabı tek kere yapar. O sonucu yerleştirecek bir yazmaç da bulabilirse kod hızlı da olur.

O yüzden hiç olmazsa o hesabı for'dan önce senin bir kere hesaplatmanı öneririm.

Bu durumda başka bir seçenek iota'dır çünkü hesap ona bir parametre olarak gittiği için tek kere işletilir. Ama sınır değer olarak ne kullanacağımdan emin olamıyorum:

import std.range;
// ...
   // k ve j artık açıkça tanımlanmıyorlar:
   uint xSay = 1;
// ...
   foreach (k; iota!ubyte(3, xAsal + 1, 2)) {
// ...
           foreach (j; iota!ubyte(3, (xAsal / k) + 1, 2)) bitSet(k * j);

Emin olamamamın nedeni, sen <= işleci kullandığın halde iota < işlecini kullanır. Yani onda sınır değerin ikincisi aralığa dahil değildir. Senin aldığın sonuçları elde edebilmek için ben 'xAsal + 1' ve '(xAsal / k) + 1' yazdım. Öyle yaptığım zaman sonuçları değiştirmiyorum, değil mi?

Ali

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

October 12, 2012

Hayırlı cumalar...:)

Cumanın bereketine yeni sürüm! Hep diyorum ya, son nokta bu artık ama yine olmadı; alın size sürüm 6:

/*
* asalTara.d (v6 - 12.10.2012)
*/
   import core.stdc.stdio : printf;

   immutable n = 982451000;            // Alt Sınır
   immutable x = 982451653;            // Üst Sınır
   immutable s  = ((x - n) / 16) + 1;  // Dizi Boyutu

   ubyte[] data;

   auto bitMask (uint k) {
       return cast(ubyte)1 << ((k % 16) >> 1);
   }

   bool bitTest (uint k) {
       if(k >= n) {
           return (data[(k - n) >> 4] & bitMask(k - n)) == 0;
       }
       return 1;
   }

   void bitSet  (uint k) {
       if(k >= n) {
           data[(k - n) >> 4] |= bitMask(k - n);
       }
   }

void main() {
   data = new ubyte[s];
   uint xSay;

   if(n <= 2) {
       xSay++;
       printf("2\t");
   }

   for(uint k = 3; k <= x; k += 2) {
       if(bitTest(k)) {
           for(uint j = 3; j <= (x / k); j += 2) bitSet(k * j);
           if(k >= n) {
               xSay++;
               printf("%u\t", k);
           }
       }
   }
   printf("\n\nToplam %u adet asal bulundu...\n", xSay);
}/* Çıktısı:
982451023	982451081	982451087	982451111	982451123	982451159	982451161
982451179	982451191	982451219	982451227	982451231	982451243	982451321
982451333	982451359	982451383	982451419	982451429	982451443	982451467
982451479	982451497	982451501	982451549	982451567	982451579	982451581
982451609	982451629	982451653

Toplam 31 adet asal bulundu...
*/

Meğer sadece bir offset değeri (n, belki x veya o olmalıydı) ile iki aralığı tarayabilirmişiz...:)

Başarılar...

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

1 2
Next ›   Last »