Şimdi Ara

project euler 7.soru

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
1 Misafir - 1 Masaüstü
5 sn
17
Cevap
1
Favori
616
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 1
Giriş
Mesaj
  • arkadaşlar 10.001inci asal sayıyı bulmak için aşağıdaki kodu yazdım ancak kodu çalıştırdığımda yalnızca siyah ekranla karşılaşıyorum.sorun nereden kaynaklanıyor olabilir?ilginiz için şimdiden teşekkürler.
    ****************
    #include<stdio.h>
    #include<conio.h>


    bool controllingprimenumber(long number){
    int k=0;
    int i=2;

    while(i<number)
    {

    if(number%i==0)
    {
    k++;
    }

    i++;


    }

    if(k==0)
    return 1;

    if(k>0)
    return 0;

    }


    int main(){

    long number=3;
    int i=0;



    while(i<=10000)
    {


    if(controllingprimenumber(number)==1)
    {
    i++;}




    number++; }



    printf("10.001st prime number is %ld",number);

    getch();

    return 0;

    }
    **************************







  • Asal sayı bulurken brute force kullanmak artık eskide kaldı. Asal sayı bulmaya yardımcı olan daha guzel algoritmalar var onları denersen bi sıkıntı olacagını sanmıyorum.
  • Ilginiz icin tesekkur ederim ama yazdigim koddaki sikinti tam olarak nerede bakabilir misiniz?

    < Bu ileti mobil sürüm kullanılarak atıldı >
  • Merhaba,

    10000. asal sayi sanirim 104729.

    Bu sayiyi bulmak icin main fonksiyonundaki while dongun 104729 kere donuyor ve controllingPrimeNumber fonksiyonunu cagiriyor. Bu fonksiyon ise kendisine verilen parametre kadar donuyor. Toplamda 104729! kadar islem yapiyorsun yani. Bu sayi o kadar buyuk ki hayatin boyunca calissa bu kod sonucu bulamayabilirsin. :) Sadece siyah ekran cikmasinin sebebi bu. Bazi iyilestirmeler yapman gerekiyor kodunda ya da yukarda dendigi gibi hizli calisan algoritmalar aramalisin.
  • Asal Sayı Test Fonskiyonunuzu Aşağıdaki Mantıkla Çalışır Hale Getirirseniz, Uygulamanızın Hızlandığını Göreceksiniz.
    Kendim Test Ettim (İşlem Süreleri Aşağıda)

    10001. Asal Sayı = 1.81 saniye
    20000. Asal Sayı = 7.54 saniye
    30000. Asal Sayı = 18.79 saniye
    40000. Asal Sayı = 36.21 saniye
    50000. Asal Sayı = 57.83 saniye


     
    /**
    * Asal Sayı Testi
    * 1 Asal Sayı Değildir,
    * Bir Sayının Asal Sayı Olabilmesi İçin, 1 ve Kendisi Dışındaki
    * Sayıların Hiçbirinin O Sayıyı Kalansız Bölmemesi Gerekir.
    * Eğer 1 - n Arasındaki Sayılardan Bir Tanesi Bile Sayıyı Kalansız
    * Bölüyorsa, Sayı Asal Değildir. Dolayısıyla Test İşlemine Devam Etmeye Gerek Yoktur
    *
    * @param n Test Edilecek Sayı
    * @return Sayı Asalsa True, Sayı Asal Değilse False Döner
    */
    public static boolean isPrime(int n)
    {
    if (n == 1) return false;
    for (int i = 2; i<n; i++)
    if (n % i == 0) return false;
    return true;
    }


    Şu an için değil, ama ileride kendinizi geliştirdiğinizde, lütfen aynı uygulamayı farklı threadler kullanarak yapmayı deneyin.
    örneğin eş zamanlı olarak 2-3 thread çalıştırıp iş yükünü bölün, harcanan sürenin %30 gibi bir oranda azaldığını göreceksiniz :)

    Yazmış olduğunuz kodtaki sıkıntı
    Siz hangi sayı olursa olsun, tüm sayıları kalansız bölüyor mu diye kontrol ediyorsunuz, halbuki 1 - n arasındaki herhangi bir sayı n'i kalansız olarak bölüyorsa, o an evet bu asal değil diye işleme devam etmelisiniz,
    bunun yerine siz, en sona kadar gidiyorsunuz.

    örneğin :
    3 - 10 arasındaki sayıların testini yapacak olursak
    (sizin programın mantığı)
    3 -> 3 kere döner
    4 -> 4 kere döner
    5 -> 5 kere döner
    6 -> 6 kere döner
    7 -> 7 kere döner
    8 -> 8 kere döner
    9 -> 9 kere döner
    10 -> 10 kere döner

    toplam = 52 kez aynı işlem tekrar edilir.

    (benim verdiğim örnekteki mantık)
    3 -> 1 kere döner
    4 -> 1 kere döner
    5 -> 3 kere döner
    6 -> 1 kere döner
    7 -> 5 kere döner
    8 -> 1 kere döner
    9 -> 2 kere döner
    10 -> 1 kere döner
    toplam = 14 kez aynı işlem tekrar edilir.

    eğer sayıları büyütecek olursak farkı anlarsınız

    10000 - 10005 arasındaki sayıların testi :

    (sizin programın mantığı)
    10000 -> 10000 kere döner
    10001 -> 10001 kere döner
    10002 -> 10002 kere döner
    10003 -> 10003 kere döner
    10004 -> 10004 kere döner
    10005 -> 10005 kere döner

    toplam = 60015 kere aynı işlem tekrar edilir

    (benim verdiğim örnekteki mantık)
    10000 -> 1 kere döner
    10001 -> 73 kere döner
    10002 -> 1 kere döner
    10003 -> 6 kere döner
    10004 -> 1 döner
    10005 -> 2 kere döner
    toplam = 84 kere aynı işlem tekrar edilir.

    umarım örnekler açıklayıcı olmuştur.



    < Bu mesaj bu kişi tarafından değiştirildi ecivas -- 1 Kasım 2014; 15:37:05 >




  • quote:

    Orijinalden alıntı: ecivas

    Asal Sayı Test Fonskiyonunuzu Aşağıdaki Mantıkla Çalışır Hale Getirirseniz, Uygulamanızın Hızlandığını Göreceksiniz.
    Kendim Test Ettim (İşlem Süreleri Aşağıda)

    10001. Asal Sayı = 1.81 saniye
    20000. Asal Sayı = 7.54 saniye
    30000. Asal Sayı = 18.79 saniye
    40000. Asal Sayı = 36.21 saniye
    50000. Asal Sayı = 57.83 saniye


     
    /**
    * Asal Sayı Testi
    * 1 Asal Sayı Değildir,
    * Bir Sayının Asal Sayı Olabilmesi İçin, 1 ve Kendisi Dışındaki
    * Sayıların Hiçbirinin O Sayıyı Kalansız Bölmemesi Gerekir.
    * Eğer 1 - n Arasındaki Sayılardan Bir Tanesi Bile Sayıyı Kalansız
    * Bölüyorsa, Sayı Asal Değildir. Dolayısıyla Test İşlemine Devam Etmeye Gerek Yoktur
    *
    * @param n Test Edilecek Sayı
    * @return Sayı Asalsa True, Sayı Asal Değilse False Döner
    */
    public static boolean isPrime(int n)
    {
    if (n == 1) return false;
    for (int i = 2; i<n; i++)
    if (n % i == 0) return false;
    return true;
    }


    Şu an için değil, ama ileride kendinizi geliştirdiğinizde, lütfen aynı uygulamayı farklı threadler kullanarak yapmayı deneyin.
    örneğin eş zamanlı olarak 2-3 thread çalıştırıp iş yükünü bölün, harcanan sürenin %30 gibi bir oranda azaldığını göreceksiniz :)

    Yazmış olduğunuz kodtaki sıkıntı
    Siz hangi sayı olursa olsun, tüm sayıları kalansız bölüyor mu diye kontrol ediyorsunuz, halbuki 1 - n arasındaki herhangi bir sayı n'i kalansız olarak bölüyorsa, o an evet bu asal değil diye işleme devam etmelisiniz,
    bunun yerine siz, en sona kadar gidiyorsunuz.

    örneğin :
    3 - 10 arasındaki sayıların testini yapacak olursak
    (sizin programın mantığı)
    3 -> 3 kere döner
    4 -> 4 kere döner
    5 -> 5 kere döner
    6 -> 6 kere döner
    7 -> 7 kere döner
    8 -> 8 kere döner
    9 -> 9 kere döner
    10 -> 10 kere döner

    toplam = 52 kez aynı işlem tekrar edilir.

    (benim verdiğim örnekteki mantık)
    3 -> 1 kere döner
    4 -> 1 kere döner
    5 -> 3 kere döner
    6 -> 1 kere döner
    7 -> 5 kere döner
    8 -> 1 kere döner
    9 -> 2 kere döner
    10 -> 1 kere döner
    toplam = 14 kez aynı işlem tekrar edilir.

    eğer sayıları büyütecek olursak farkı anlarsınız

    10000 - 10005 arasındaki sayıların testi :

    (sizin programın mantığı)
    10000 -> 10000 kere döner
    10001 -> 10001 kere döner
    10002 -> 10002 kere döner
    10003 -> 10003 kere döner
    10004 -> 10004 kere döner
    10005 -> 10005 kere döner

    toplam = 60015 kere aynı işlem tekrar edilir

    (benim verdiğim örnekteki mantık)
    10000 -> 1 kere döner
    10001 -> 73 kere döner
    10002 -> 1 kere döner
    10003 -> 6 kere döner
    10004 -> 1 döner
    10005 -> 2 kere döner
    toplam = 84 kere aynı işlem tekrar edilir.

    umarım örnekler açıklayıcı olmuştur.



    Daha iyi algoritmalar da var:

    http://en.wikibooks.org/wiki/Efficient_Prime_Number_Generating_Algorithms

    Burada bakicak olursak en son verilen algoritma 10000. ci sayiyi 0.01 saniyede veriyor. Ilk algoritma bile 10000. ci sayiyi 1.6 saniyede veriyor.

    Yapilmasi basit ve anlasilir olan 3. algoritma. Tabi bunu anlamak icin ilk 2 algoritmayi anlamak gerekiyor.

    1. algoritma:
    Sayi asal mi degil mi bunu ogrenmek icin elimizde bir liste olur ve bu listede sadece karsilastigimiz asal sayilar bulunur, mevcut sayi bu listedeki sayilara bolunmuyorsa mevcut sayi bu listeye eklenir. Mevcut listeye 2 sayisini ekleyerek basliyoruz ve 3 ten itibaren baslayarak bu algoritmayi uyguluyoruz. (100 000 inci sayiya 130 saniyede ulasiyor bu algoritma)

    2. algoritma:
    2 den baska hic bir cift sayi asal degildir. O zaman neden 2 ile ugrasiyoruz ki? 3 ten baslayip sayiyi cifter cifter arttirirsak hep tek sayilara bakmis oluruz. (100 000 inci sayiya 65 saniyede ulasiyor)

    3. algoritma:
    Baktigimiz sayinin karekoku eger listedeki bolmeyi kontrol ettigimiz sayidan buyukse o zaman listeye bakmaya devam etmeye gerek yoktur, cunku karekokunden buyuk sayilar asal sayinin kendi bolumu olamaz. (100 000 inci sayiya 27 saniyede ulasiyor)




  • gösterdiginiz ilgiden dolayı hepinize teşekkür ederim :)
  • Yukarıda verilen sitedeki algoritma n. asal sayıyı değil, n'e kadar olan asal sayıları veriyordu dolayısıyla biraz bi değişiklik yaptım, 10000. asal sayıyı (değişiyor sürekli ama) 300-350 ms'de falan buluyorum, kullandığım kod şu (birebir geçirmeye çalıştım, C#);
    static List<long> allPrimes(long n) 
    {
    long pp = 2;
    int sqrtPP;
    bool test;
    List<long> allPrime = new List<long>();
    pp++;
    allPrime.Add(pp);
    while (pp < n)
    {
    pp += 2;
    test = true;
    sqrtPP = (int)Math.Sqrt(pp);
    for (int i = 0; i < allPrime.Count; i++)
    {

    if (allPrime[i] > sqrtPP)
    break;
    if (pp % allPrime[i] == 0)
    {
    test = false;
    break;
    }
    if (test)
    {
    allPrime.Add(pp);
    }
    }
    }
    return allPrime;
    }

    Benzer bir mantıkla çalışan kendi kodum ise 350-450 ms arasında sonuç veriyor;
    static long ninciAsal(int n) 
    {
    List<long> asallar = new List<long>();
    long l = 2;
    long lastAsal = 0;
    int i = 0;
    while (i < n)
    {
    while (!asal(l, asallar))
    {
    l++;
    }
    asallar.Add(l);
    lastAsal = l;
    l++;
    i++;
    }
    return lastAsal;
    }

    static bool asal(long sayi, List<long> asallar)
    {
    if (sayi > 1)
    {
    bool asal = true;
    int maxi = 0;
    long sayiKok = (long)Math.Sqrt(sayi);
    foreach (long l in asallar)
    {
    if (l <= sayiKok)
    {
    maxi++;
    }
    else
    {
    break;
    }
    }
    for (int i = 0; i < maxi; i++)
    {
    if (sayi % asallar[i] == 0)
    {
    asal = false;
    break;
    }
    }
    return asal;
    }
    else
    {
    return false;
    }
    }


    Bu 100 ms'lik fark nereden kaynaklanıyor olabilir? Kodumda değişiklik yapılması gereken yerler mi var acaba?

    Kullanım;

     
    Stopwatch sw = Stopwatch.StartNew();
    long l = ninciAsal(10000);//kendi fonksiyonum
    sw.Stop();
    Console.WriteLine(ninciAsal(10000));
    Console.WriteLine("Found in : " + sw.ElapsedMilliseconds.ToString());
    sw.Restart();
    List<long> allprms = allPrimes(l);//sitedeki algoritmanın C#'a dönüştürülmüş hali (olduğu kadar)
    sw.Stop();
    Console.WriteLine(allprms[allprms.Count - 1]);
    Console.WriteLine("Found in: " + sw.ElapsedMilliseconds);




  • En cok kullanilan yontemlerden bir tanesi kriptografide.
    http://en.wikipedia.org/wiki/Fermat_primality_test
  • quote:

    Orijinalden alıntı: ThisisaNightmare

    quote:

    Orijinalden alıntı: ecivas

    Asal Sayı Test Fonskiyonunuzu Aşağıdaki Mantıkla Çalışır Hale Getirirseniz, Uygulamanızın Hızlandığını Göreceksiniz.
    Kendim Test Ettim (İşlem Süreleri Aşağıda)

    10001. Asal Sayı = 1.81 saniye
    20000. Asal Sayı = 7.54 saniye
    30000. Asal Sayı = 18.79 saniye
    40000. Asal Sayı = 36.21 saniye
    50000. Asal Sayı = 57.83 saniye


     
    /**
    * Asal Sayı Testi
    * 1 Asal Sayı Değildir,
    * Bir Sayının Asal Sayı Olabilmesi İçin, 1 ve Kendisi Dışındaki
    * Sayıların Hiçbirinin O Sayıyı Kalansız Bölmemesi Gerekir.
    * Eğer 1 - n Arasındaki Sayılardan Bir Tanesi Bile Sayıyı Kalansız
    * Bölüyorsa, Sayı Asal Değildir. Dolayısıyla Test İşlemine Devam Etmeye Gerek Yoktur
    *
    * @param n Test Edilecek Sayı
    * @return Sayı Asalsa True, Sayı Asal Değilse False Döner
    */
    public static boolean isPrime(int n)
    {
    if (n == 1) return false;
    for (int i = 2; i<n; i++)
    if (n % i == 0) return false;
    return true;
    }


    Şu an için değil, ama ileride kendinizi geliştirdiğinizde, lütfen aynı uygulamayı farklı threadler kullanarak yapmayı deneyin.
    örneğin eş zamanlı olarak 2-3 thread çalıştırıp iş yükünü bölün, harcanan sürenin %30 gibi bir oranda azaldığını göreceksiniz :)

    Yazmış olduğunuz kodtaki sıkıntı
    Siz hangi sayı olursa olsun, tüm sayıları kalansız bölüyor mu diye kontrol ediyorsunuz, halbuki 1 - n arasındaki herhangi bir sayı n'i kalansız olarak bölüyorsa, o an evet bu asal değil diye işleme devam etmelisiniz,
    bunun yerine siz, en sona kadar gidiyorsunuz.

    örneğin :
    3 - 10 arasındaki sayıların testini yapacak olursak
    (sizin programın mantığı)
    3 -> 3 kere döner
    4 -> 4 kere döner
    5 -> 5 kere döner
    6 -> 6 kere döner
    7 -> 7 kere döner
    8 -> 8 kere döner
    9 -> 9 kere döner
    10 -> 10 kere döner

    toplam = 52 kez aynı işlem tekrar edilir.

    (benim verdiğim örnekteki mantık)
    3 -> 1 kere döner
    4 -> 1 kere döner
    5 -> 3 kere döner
    6 -> 1 kere döner
    7 -> 5 kere döner
    8 -> 1 kere döner
    9 -> 2 kere döner
    10 -> 1 kere döner
    toplam = 14 kez aynı işlem tekrar edilir.

    eğer sayıları büyütecek olursak farkı anlarsınız

    10000 - 10005 arasındaki sayıların testi :

    (sizin programın mantığı)
    10000 -> 10000 kere döner
    10001 -> 10001 kere döner
    10002 -> 10002 kere döner
    10003 -> 10003 kere döner
    10004 -> 10004 kere döner
    10005 -> 10005 kere döner

    toplam = 60015 kere aynı işlem tekrar edilir

    (benim verdiğim örnekteki mantık)
    10000 -> 1 kere döner
    10001 -> 73 kere döner
    10002 -> 1 kere döner
    10003 -> 6 kere döner
    10004 -> 1 döner
    10005 -> 2 kere döner
    toplam = 84 kere aynı işlem tekrar edilir.

    umarım örnekler açıklayıcı olmuştur.



    Daha iyi algoritmalar da var:

    http://en.wikibooks.org/wiki/Efficient_Prime_Number_Generating_Algorithms

    Burada bakicak olursak en son verilen algoritma 10000. ci sayiyi 0.01 saniyede veriyor. Ilk algoritma bile 10000. ci sayiyi 1.6 saniyede veriyor.

    Yapilmasi basit ve anlasilir olan 3. algoritma. Tabi bunu anlamak icin ilk 2 algoritmayi anlamak gerekiyor.

    1. algoritma:
    Sayi asal mi degil mi bunu ogrenmek icin elimizde bir liste olur ve bu listede sadece karsilastigimiz asal sayilar bulunur, mevcut sayi bu listedeki sayilara bolunmuyorsa mevcut sayi bu listeye eklenir. Mevcut listeye 2 sayisini ekleyerek basliyoruz ve 3 ten itibaren baslayarak bu algoritmayi uyguluyoruz. (100 000 inci sayiya 130 saniyede ulasiyor bu algoritma)

    2. algoritma:
    2 den baska hic bir cift sayi asal degildir. O zaman neden 2 ile ugrasiyoruz ki? 3 ten baslayip sayiyi cifter cifter arttirirsak hep tek sayilara bakmis oluruz. (100 000 inci sayiya 65 saniyede ulasiyor)

    3. algoritma:
    Baktigimiz sayinin karekoku eger listedeki bolmeyi kontrol ettigimiz sayidan buyukse o zaman listeye bakmaya devam etmeye gerek yoktur, cunku karekokunden buyuk sayilar asal sayinin kendi bolumu olamaz. (100 000 inci sayiya 27 saniyede ulasiyor)

    Alıntıları Göster
    Algoritmalar güzel, tabii ki daha iyileri var :)
    ama başlangıç seviyesi için, ve arkadaşın yazdığı kodta, döngüyü sonuna kadar devam ettirip, ettirmemenin neleri farkettiğini göstermek için bu algoritma üstünde durdum :)




  • quote:

    Orijinalden alıntı: welrocken

    Yukarıda verilen sitedeki algoritma n. asal sayıyı değil, n'e kadar olan asal sayıları veriyordu dolayısıyla biraz bi değişiklik yaptım, 10000. asal sayıyı (değişiyor sürekli ama) 300-350 ms'de falan buluyorum, kullandığım kod şu (birebir geçirmeye çalıştım, C#);
    static List<long> allPrimes(long n) 
    {
    long pp = 2;
    int sqrtPP;
    bool test;
    List<long> allPrime = new List<long>();
    pp++;
    allPrime.Add(pp);
    while (pp < n)
    {
    pp += 2;
    test = true;
    sqrtPP = (int)Math.Sqrt(pp);
    for (int i = 0; i < allPrime.Count; i++)
    {

    if (allPrime[i] > sqrtPP)
    break;
    if (pp % allPrime[i] == 0)
    {
    test = false;
    break;
    }
    if (test)
    {
    allPrime.Add(pp);
    }
    }
    }
    return allPrime;
    }

    Benzer bir mantıkla çalışan kendi kodum ise 350-450 ms arasında sonuç veriyor;
    static long ninciAsal(int n) 
    {
    List<long> asallar = new List<long>();
    long l = 2;
    long lastAsal = 0;
    int i = 0;
    while (i < n)
    {
    while (!asal(l, asallar))
    {
    l++;
    }
    asallar.Add(l);
    lastAsal = l;
    l++;
    i++;
    }
    return lastAsal;
    }

    static bool asal(long sayi, List<long> asallar)
    {
    if (sayi > 1)
    {
    bool asal = true;
    int maxi = 0;
    long sayiKok = (long)Math.Sqrt(sayi);
    foreach (long l in asallar)
    {
    if (l <= sayiKok)
    {
    maxi++;
    }
    else
    {
    break;
    }
    }
    for (int i = 0; i < maxi; i++)
    {
    if (sayi % asallar[i] == 0)
    {
    asal = false;
    break;
    }
    }
    return asal;
    }
    else
    {
    return false;
    }
    }


    Bu 100 ms'lik fark nereden kaynaklanıyor olabilir? Kodumda değişiklik yapılması gereken yerler mi var acaba?

    Kullanım;

     
    Stopwatch sw = Stopwatch.StartNew();
    long l = ninciAsal(10000);//kendi fonksiyonum
    sw.Stop();
    Console.WriteLine(ninciAsal(10000));
    Console.WriteLine("Found in : " + sw.ElapsedMilliseconds.ToString());
    sw.Restart();
    List<long> allprms = allPrimes(l);//sitedeki algoritmanın C#'a dönüştürülmüş hali (olduğu kadar)
    sw.Stop();
    Console.WriteLine(allprms[allprms.Count - 1]);
    Console.WriteLine("Found in: " + sw.ElapsedMilliseconds);



    While loopunda sadece 1 ekliyorsun 2 eklemek yerine. asallar.Add(2) deyip l i 3 ten baslatirsan while dongusunun icindede l i 2 ser 2 ser arttirirsan algoritma hizlanir gibi duruyor.
    2. olarak ise asal methodunda foreach loop ile for loopun var. For loop gereksiz duruyor. Foreach loopunda yapmak istedigini direkt yapmalisin gerek yok maxi yapip saymaya. Yapicagini orada yap (sayi buyuk mu check et, daha sonra bolunuyor mu onu check et)



    < Bu mesaj bu kişi tarafından değiştirildi ThisisaNightmare -- 2 Kasım 2014; 22:49:56 >




  • quote:

    Orijinalden alıntı: ThisisaNightmare

    quote:

    Orijinalden alıntı: welrocken

    Yukarıda verilen sitedeki algoritma n. asal sayıyı değil, n'e kadar olan asal sayıları veriyordu dolayısıyla biraz bi değişiklik yaptım, 10000. asal sayıyı (değişiyor sürekli ama) 300-350 ms'de falan buluyorum, kullandığım kod şu (birebir geçirmeye çalıştım, C#);
    static List<long> allPrimes(long n) 
    {
    long pp = 2;
    int sqrtPP;
    bool test;
    List<long> allPrime = new List<long>();
    pp++;
    allPrime.Add(pp);
    while (pp < n)
    {
    pp += 2;
    test = true;
    sqrtPP = (int)Math.Sqrt(pp);
    for (int i = 0; i < allPrime.Count; i++)
    {

    if (allPrime[i] > sqrtPP)
    break;
    if (pp % allPrime[i] == 0)
    {
    test = false;
    break;
    }
    if (test)
    {
    allPrime.Add(pp);
    }
    }
    }
    return allPrime;
    }

    Benzer bir mantıkla çalışan kendi kodum ise 350-450 ms arasında sonuç veriyor;
    static long ninciAsal(int n) 
    {
    List<long> asallar = new List<long>();
    long l = 2;
    long lastAsal = 0;
    int i = 0;
    while (i < n)
    {
    while (!asal(l, asallar))
    {
    l++;
    }
    asallar.Add(l);
    lastAsal = l;
    l++;
    i++;
    }
    return lastAsal;
    }

    static bool asal(long sayi, List<long> asallar)
    {
    if (sayi > 1)
    {
    bool asal = true;
    int maxi = 0;
    long sayiKok = (long)Math.Sqrt(sayi);
    foreach (long l in asallar)
    {
    if (l <= sayiKok)
    {
    maxi++;
    }
    else
    {
    break;
    }
    }
    for (int i = 0; i < maxi; i++)
    {
    if (sayi % asallar[i] == 0)
    {
    asal = false;
    break;
    }
    }
    return asal;
    }
    else
    {
    return false;
    }
    }


    Bu 100 ms'lik fark nereden kaynaklanıyor olabilir? Kodumda değişiklik yapılması gereken yerler mi var acaba?

    Kullanım;

     
    Stopwatch sw = Stopwatch.StartNew();
    long l = ninciAsal(10000);//kendi fonksiyonum
    sw.Stop();
    Console.WriteLine(ninciAsal(10000));
    Console.WriteLine("Found in : " + sw.ElapsedMilliseconds.ToString());
    sw.Restart();
    List<long> allprms = allPrimes(l);//sitedeki algoritmanın C#'a dönüştürülmüş hali (olduğu kadar)
    sw.Stop();
    Console.WriteLine(allprms[allprms.Count - 1]);
    Console.WriteLine("Found in: " + sw.ElapsedMilliseconds);



    While loopunda sadece 1 ekliyorsun 2 eklemek yerine. asallar.Add(2) deyip l i 3 ten baslatirsan while dongusunun icindede l i 2 ser 2 ser arttirirsan algoritma hizlanir gibi duruyor.
    2. olarak ise asal methodunda foreach loop ile for loopun var. For loop gereksiz duruyor. Foreach loopunda yapmak istedigini direkt yapmalisin gerek yok maxi yapip saymaya. Yapicagini orada yap (sayi buyuk mu check et, daha sonra bolunuyor mu onu check et)

    Teşekkür ederim, deniyim, bir de okulda bir derste (Discreate Math di galiba) bir algoritmanın çalışma süresi ile ilgili birşey öğrenmiştik. Döngüler, tekrar edilen şeyler polinom olarak yazıp (iki iç içe döngü sanırım n^2 olarak yazılıyordu [ikisi de n kere dönüyorsa]), matematiksel işlemleri vs. constant olarak varsayıp işlem yapıyorduk (ve hesaba katmıyorduk, ama buradaki süre ölçerler herşeyi hesaba katıyor dolaylı olarak). Demek istediğim, bu süreler sadece bir deney sonucu, mesela benim kodum diğer algoritmadan çoğu denememde yaklaşık 100-150 ms uzun sürüyor ama belki de matematiğini yapsam, n sayısı çok büyüdüğünde 2 katı 10 katı vs. uzun sürecek. Dolayısıyla bu sürelere güvenmeli mi, yoksa oturup matematiksel hesabını mı yapmalı?

    Sitedeki algoritmaların mantığı çok anlaşılır da burada paylaşılan o efsane kodu çözemedim, adresleme bilgimden kaynaklanıyor olabilir * ve & gördüğüm yerde bi korku basıyor, açıklaması var mıdır bi yerde?

    Edit: efsane kod şu konudaymış kafa gitmiş;
    http://forum.donanimhaber.com/m_98945826/tm.htm



    < Bu mesaj bu kişi tarafından değiştirildi welrocken -- 2 Kasım 2014; 17:16:30 >




  • buyuk hesaplamalarda divide and conquer metodunu kullanamk iyi bir secenek olabilir.
  • quote:

    Orijinalden alıntı: welrocken

    quote:

    Orijinalden alıntı: ThisisaNightmare

    quote:

    Orijinalden alıntı: welrocken

    Yukarıda verilen sitedeki algoritma n. asal sayıyı değil, n'e kadar olan asal sayıları veriyordu dolayısıyla biraz bi değişiklik yaptım, 10000. asal sayıyı (değişiyor sürekli ama) 300-350 ms'de falan buluyorum, kullandığım kod şu (birebir geçirmeye çalıştım, C#);
    static List<long> allPrimes(long n) 
    {
    long pp = 2;
    int sqrtPP;
    bool test;
    List<long> allPrime = new List<long>();
    pp++;
    allPrime.Add(pp);
    while (pp < n)
    {
    pp += 2;
    test = true;
    sqrtPP = (int)Math.Sqrt(pp);
    for (int i = 0; i < allPrime.Count; i++)
    {

    if (allPrime[i] > sqrtPP)
    break;
    if (pp % allPrime[i] == 0)
    {
    test = false;
    break;
    }
    if (test)
    {
    allPrime.Add(pp);
    }
    }
    }
    return allPrime;
    }

    Benzer bir mantıkla çalışan kendi kodum ise 350-450 ms arasında sonuç veriyor;
    static long ninciAsal(int n) 
    {
    List<long> asallar = new List<long>();
    long l = 2;
    long lastAsal = 0;
    int i = 0;
    while (i < n)
    {
    while (!asal(l, asallar))
    {
    l++;
    }
    asallar.Add(l);
    lastAsal = l;
    l++;
    i++;
    }
    return lastAsal;
    }

    static bool asal(long sayi, List<long> asallar)
    {
    if (sayi > 1)
    {
    bool asal = true;
    int maxi = 0;
    long sayiKok = (long)Math.Sqrt(sayi);
    foreach (long l in asallar)
    {
    if (l <= sayiKok)
    {
    maxi++;
    }
    else
    {
    break;
    }
    }
    for (int i = 0; i < maxi; i++)
    {
    if (sayi % asallar[i] == 0)
    {
    asal = false;
    break;
    }
    }
    return asal;
    }
    else
    {
    return false;
    }
    }


    Bu 100 ms'lik fark nereden kaynaklanıyor olabilir? Kodumda değişiklik yapılması gereken yerler mi var acaba?

    Kullanım;

     
    Stopwatch sw = Stopwatch.StartNew();
    long l = ninciAsal(10000);//kendi fonksiyonum
    sw.Stop();
    Console.WriteLine(ninciAsal(10000));
    Console.WriteLine("Found in : " + sw.ElapsedMilliseconds.ToString());
    sw.Restart();
    List<long> allprms = allPrimes(l);//sitedeki algoritmanın C#'a dönüştürülmüş hali (olduğu kadar)
    sw.Stop();
    Console.WriteLine(allprms[allprms.Count - 1]);
    Console.WriteLine("Found in: " + sw.ElapsedMilliseconds);



    While loopunda sadece 1 ekliyorsun 2 eklemek yerine. asallar.Add(2) deyip l i 3 ten baslatirsan while dongusunun icindede l i 2 ser 2 ser arttirirsan algoritma hizlanir gibi duruyor.
    2. olarak ise asal methodunda foreach loop ile for loopun var. For loop gereksiz duruyor. Foreach loopunda yapmak istedigini direkt yapmalisin gerek yok maxi yapip saymaya. Yapicagini orada yap (sayi buyuk mu check et, daha sonra bolunuyor mu onu check et)

    Teşekkür ederim, deniyim, bir de okulda bir derste (Discreate Math di galiba) bir algoritmanın çalışma süresi ile ilgili birşey öğrenmiştik. Döngüler, tekrar edilen şeyler polinom olarak yazıp (iki iç içe döngü sanırım n^2 olarak yazılıyordu [ikisi de n kere dönüyorsa]), matematiksel işlemleri vs. constant olarak varsayıp işlem yapıyorduk (ve hesaba katmıyorduk, ama buradaki süre ölçerler herşeyi hesaba katıyor dolaylı olarak). Demek istediğim, bu süreler sadece bir deney sonucu, mesela benim kodum diğer algoritmadan çoğu denememde yaklaşık 100-150 ms uzun sürüyor ama belki de matematiğini yapsam, n sayısı çok büyüdüğünde 2 katı 10 katı vs. uzun sürecek. Dolayısıyla bu sürelere güvenmeli mi, yoksa oturup matematiksel hesabını mı yapmalı?

    Sitedeki algoritmaların mantığı çok anlaşılır da burada paylaşılan o efsane kodu çözemedim, adresleme bilgimden kaynaklanıyor olabilir * ve & gördüğüm yerde bi korku basıyor, açıklaması var mıdır bi yerde?

    Edit: efsane kod şu konudaymış kafa gitmiş;
    http://forum.donanimhaber.com/m_98945826/tm.htm

    Sorunun hacmine gore degisir bu soru. Yeri gelir bir sorun icin bir algoritma kurman gerekir bu algoritma O((n^2)/1000) olabilir ve baskasi gelipte sana benim O(n*10000) algoritmam var seninkisinden daha iyi diyebilir. Fakat gercek hayatta ancak n = 10000000 iken bu iki algoritmanin calisma suresi birbirine esit olur cunku (10000000^2)÷1000 = 10000000*10000. Eger sen elindeki listenin 10 milyon elemandan az oldugunu surekli ispatlarsan o zaman constant degerleri ele alabilirsin, fakat bunu ispatlayamazsan o zaman O(n^2) ile O(n) karsilasitmasi olur, bu yuzdende 2. algoritma daha hizlidir deriz (cunku n sonsuza gider).
    Kendi yaptigin surelerin karsilastirmasiyla asymptotic complexity nin karsilasitirmak dogru olmaz. Birde o sitedeki kullanilan dil senin kullandigin dilden farkli olabilir, donanimda farkli olabilir. Ornegin dedigin gibi matematiksel islemleri saymayiz, fakat senin islemcin bir matematiksel islemi constant zamanda yapamazken karsi tarafinki yapabiliyor olabilir. Eger mantikli bir karsilastirma yapmak istiyorsan n sayisini al(atiyorum 100) bunun zamanini al (atiyorum 1 saniye) simdi x sayisi al (atiyorum 1000) n*x in zamanini al (atiyorum 10000 saniye) n*x in zamanini n e bol (10000 saniye) o zaman diyebiliriz ki bu yapilan testte karsi tarafin 100. sayiyla 100000. ci sayinin orani a dir. Bu orani kendi sonucunla karsilastir, yakin bir sonucsa algoritmanin runtime complexity si buyuk ihtimalle aynidir, x sayisi ne kadar buyukse bu yakinliktan o kadar emin oluruz.




  • quote:

    Orijinalden alıntı: ThisisaNightmare

    quote:

    Orijinalden alıntı: welrocken

    quote:

    Orijinalden alıntı: ThisisaNightmare

    quote:

    Orijinalden alıntı: welrocken

    Yukarıda verilen sitedeki algoritma n. asal sayıyı değil, n'e kadar olan asal sayıları veriyordu dolayısıyla biraz bi değişiklik yaptım, 10000. asal sayıyı (değişiyor sürekli ama) 300-350 ms'de falan buluyorum, kullandığım kod şu (birebir geçirmeye çalıştım, C#);
    static List<long> allPrimes(long n) 
    {
    long pp = 2;
    int sqrtPP;
    bool test;
    List<long> allPrime = new List<long>();
    pp++;
    allPrime.Add(pp);
    while (pp < n)
    {
    pp += 2;
    test = true;
    sqrtPP = (int)Math.Sqrt(pp);
    for (int i = 0; i < allPrime.Count; i++)
    {

    if (allPrime[i] > sqrtPP)
    break;
    if (pp % allPrime[i] == 0)
    {
    test = false;
    break;
    }
    if (test)
    {
    allPrime.Add(pp);
    }
    }
    }
    return allPrime;
    }

    Benzer bir mantıkla çalışan kendi kodum ise 350-450 ms arasında sonuç veriyor;
    static long ninciAsal(int n) 
    {
    List<long> asallar = new List<long>();
    long l = 2;
    long lastAsal = 0;
    int i = 0;
    while (i < n)
    {
    while (!asal(l, asallar))
    {
    l++;
    }
    asallar.Add(l);
    lastAsal = l;
    l++;
    i++;
    }
    return lastAsal;
    }

    static bool asal(long sayi, List<long> asallar)
    {
    if (sayi > 1)
    {
    bool asal = true;
    int maxi = 0;
    long sayiKok = (long)Math.Sqrt(sayi);
    foreach (long l in asallar)
    {
    if (l <= sayiKok)
    {
    maxi++;
    }
    else
    {
    break;
    }
    }
    for (int i = 0; i < maxi; i++)
    {
    if (sayi % asallar[i] == 0)
    {
    asal = false;
    break;
    }
    }
    return asal;
    }
    else
    {
    return false;
    }
    }


    Bu 100 ms'lik fark nereden kaynaklanıyor olabilir? Kodumda değişiklik yapılması gereken yerler mi var acaba?

    Kullanım;

     
    Stopwatch sw = Stopwatch.StartNew();
    long l = ninciAsal(10000);//kendi fonksiyonum
    sw.Stop();
    Console.WriteLine(ninciAsal(10000));
    Console.WriteLine("Found in : " + sw.ElapsedMilliseconds.ToString());
    sw.Restart();
    List<long> allprms = allPrimes(l);//sitedeki algoritmanın C#'a dönüştürülmüş hali (olduğu kadar)
    sw.Stop();
    Console.WriteLine(allprms[allprms.Count - 1]);
    Console.WriteLine("Found in: " + sw.ElapsedMilliseconds);



    While loopunda sadece 1 ekliyorsun 2 eklemek yerine. asallar.Add(2) deyip l i 3 ten baslatirsan while dongusunun icindede l i 2 ser 2 ser arttirirsan algoritma hizlanir gibi duruyor.
    2. olarak ise asal methodunda foreach loop ile for loopun var. For loop gereksiz duruyor. Foreach loopunda yapmak istedigini direkt yapmalisin gerek yok maxi yapip saymaya. Yapicagini orada yap (sayi buyuk mu check et, daha sonra bolunuyor mu onu check et)

    Teşekkür ederim, deniyim, bir de okulda bir derste (Discreate Math di galiba) bir algoritmanın çalışma süresi ile ilgili birşey öğrenmiştik. Döngüler, tekrar edilen şeyler polinom olarak yazıp (iki iç içe döngü sanırım n^2 olarak yazılıyordu [ikisi de n kere dönüyorsa]), matematiksel işlemleri vs. constant olarak varsayıp işlem yapıyorduk (ve hesaba katmıyorduk, ama buradaki süre ölçerler herşeyi hesaba katıyor dolaylı olarak). Demek istediğim, bu süreler sadece bir deney sonucu, mesela benim kodum diğer algoritmadan çoğu denememde yaklaşık 100-150 ms uzun sürüyor ama belki de matematiğini yapsam, n sayısı çok büyüdüğünde 2 katı 10 katı vs. uzun sürecek. Dolayısıyla bu sürelere güvenmeli mi, yoksa oturup matematiksel hesabını mı yapmalı?

    Sitedeki algoritmaların mantığı çok anlaşılır da burada paylaşılan o efsane kodu çözemedim, adresleme bilgimden kaynaklanıyor olabilir * ve & gördüğüm yerde bi korku basıyor, açıklaması var mıdır bi yerde?

    Edit: efsane kod şu konudaymış kafa gitmiş;
    http://forum.donanimhaber.com/m_98945826/tm.htm

    Sorunun hacmine gore degisir bu soru. Yeri gelir bir sorun icin bir algoritma kurman gerekir bu algoritma O((n^2)/1000) olabilir ve baskasi gelipte sana benim O(n*10000) algoritmam var seninkisinden daha iyi diyebilir. Fakat gercek hayatta ancak n = 10000000 iken bu iki algoritmanin calisma suresi birbirine esit olur cunku (10000000^2)÷1000 = 10000000*10000. Eger sen elindeki listenin 10 milyon elemandan az oldugunu surekli ispatlarsan o zaman constant degerleri ele alabilirsin, fakat bunu ispatlayamazsan o zaman O(n^2) ile O(n) karsilasitmasi olur, bu yuzdende 2. algoritma daha hizlidir deriz (cunku n sonsuza gider).
    Kendi yaptigin surelerin karsilastirmasiyla asymptotic complexity nin karsilasitirmak dogru olmaz. Birde o sitedeki kullanilan dil senin kullandigin dilden farkli olabilir, donanimda farkli olabilir. Ornegin dedigin gibi matematiksel islemleri saymayiz, fakat senin islemcin bir matematiksel islemi constant zamanda yapamazken karsi tarafinki yapabiliyor olabilir. Eger mantikli bir karsilastirma yapmak istiyorsan n sayisini al(atiyorum 100) bunun zamanini al (atiyorum 1 saniye) simdi x sayisi al (atiyorum 1000) n*x in zamanini al (atiyorum 10000 saniye) n*x in zamanini n e bol (10000 saniye) o zaman diyebiliriz ki bu yapilan testte karsi tarafin 100. sayiyla 100000. ci sayinin orani a dir. Bu orani kendi sonucunla karsilastir, yakin bir sonucsa algoritmanin runtime complexity si buyuk ihtimalle aynidir, x sayisi ne kadar buyukse bu yakinliktan o kadar emin oluruz.

    Bu işin bir standardı yok mudur? Ne biliyim karekök alma işlemini (öyle bir built-in işlem var mı işlemcilerde bilmiyorum, yoksa da aynı algoritma & aynı kod için diyelim) her işlemci aynı sürede yapamıyorsa, örneğin o sitedeki algoritma süresi yazılırken "normal süre" + "işlemci farkından oluşabilecek farklar" (deneylerdeki error gibi)?




  • blockchain projesinde freelance yazılımcı olarak çalışmak isteyen var mı?
  • 
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.