Şimdi Ara

sqrt() fonksiyonu

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
2 Misafir - 2 Masaüstü
5 sn
15
Cevap
0
Favori
24.437
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 1
Giriş
Mesaj
  • merhabalar,
    bu math.h da bulunna sqrt() fonksiyonu nasıl çalışıyor bileniniz var mı acaba?
    Bir gündür 5-6 farklı karekök algoritması kullandım en fazla yarısı kadar hızlı olabildi o da durum bağlı.
    Acaba bir lookup table 'mi kullanıyor? Yardımcı olabilecek var mı?



  • en basit bir örnekle anlatmak gerekirse ;

    # include<stdio.h>
    # include<math.h>
    void main()
    {
    float a;
    printf ("sayi giriniz :");
    scanf("%f",&a);

    printf("sonuc %f",sqrt(a));
    }



    sqrt () fonk. nunun parantez içine bir sayida girilebilirdi . Ama bn kullanıcıdan almak istedim onun için parantez içine değişken atadim. son olarak ta sonuc virgüllü cıkma ihtimali olabiliceğindne dolayı da float kullandım

  • Visual basic 2005 'te


    textbox2.text=math.sqrt(textbox1.text) şeklinde oluyo.Karekök alıyo küpkök almayı bende bilmiyorum.
  • benim sordugum cok daha farkli bir soru!!
  • en basit bir örnekle anlatmak gerekirse ;

    # include<stdio.h>
    # include<math.h>
    void main()
    {
    float a;
    printf ("sayi giriniz :");
    scanf("%f",&a);

    printf("sonuc %f",sqrt(a));
    }



    sqrt () fonk. nunun parantez içine bir sayida girilebilirdi . Ama bn kullanıcıdan almak istedim onun için parantez içine değişken atadim. son olarak ta sonuc virgüllü cıkma ihtimali olabiliceğindne dolayı da float kullandım





  • :)

    Arkadaş tamamen farklı birşey sormuş ya, neyse.

    @g_un_es;

    arkadaşım senin sorunun cevabını bilmiyorum ancak senin kendi yazdığın karekök alma algoritmalarından bir örnek gönderebilirmisin ya da şöyle ufaktan bir bahsetsen nasıl yaptığın hakkında ? basit bir döngü içerisinde belirli koşullar ile 0 dan başlayıp sayıya yaklaşarak her seferinde kendisi ile çarpıp bunu bir if içerisinde kontrol ederek yapmak aklıma gelen tek çözüm yolu. Ancak duyarlılığı noktadan sonra 8 basamak gibi artırdığımda bu işlemin çook uzun süreceği kanısındayım. Daha farklı bir algoritma nasıl kurulabilir karekök almak için ?
  • en basit örneği vereyim:
    81 karekökünü 5 diye sallayalım. İşlemleri sadece tamsayılarda düşünürsek
    81/5= 16 O zaman (16+5)/2=10 81'in kareköküne daha yakındır.
    81/10=8, (8+10)/2=9 81'in kareköküne daha yakındır.
    81/9=9 karekökü bulduk.
    Bu bazen 9-10 arasında gidip gelebilir, fonksiyon ona göre yazılırsa bi sorun çıkmaz.
    Bu algoritmayla en fazla 16 adımda int türünün tutabileceği en büyük sayının yani 2^32-1'in karekökünü bulmak mümkün.
    Ki bu algoritma double türler içinde geçerli ama ben int'i bulsam yeter şimdilik.



    < Bu mesaj bu kişi tarafından değiştirildi g_un_es -- 7 Şubat 2008; 13:03:25 >
  •  
    int karekok(int sayi)
    {
    int k,m,n,ikililer[5],gecici1,gecici2,karekok;

    if (sayi==0) return 0;

    k=0;
    while(sayi) {
    ikililer[k]=sayi%100;
    sayi=sayi/100;
    k++;
    }
    k--;

    if (ikililer[k]<4) karekok=1;
    else if (ikililer[k]<9) karekok=2;
    else if (ikililer[k]<16) karekok=3;
    else if (ikililer[k]<25) karekok=4;
    else if (ikililer[k]<36) karekok=5;
    else if (ikililer[k]<49) karekok=6;
    else if (ikililer[k]<64) karekok=7;
    else if (ikililer[k]<81) karekok=8;
    else if (ikililer[k]<100) karekok=9;

    gecici1=ikililer[k]-karekok*karekok;

    for(m=1;m<=k;m++) {
    gecici1=gecici1*100+ikililer[k-m];
    gecici2=10*karekok*2;
    for (n=0;n<9;n++)
    if ((gecici2+n)*n>gecici1) {
    n--;
    break;
    }
    gecici2=(gecici2+n)*n;
    karekok=karekok*10+n;
    gecici1-=gecici2;
    }

    return karekok;
    }


    Bu kendi yazdığım fonksiyon. Kendisinden büyük olmayan en büyük tamkare sayının karekökünü veriyor. Double kullanılırsa ve bir iki satır daha eklenirse sqrt() nin yaptığı işin aynısını yapan hale gelebilir. Denemek için 1 den 10 000 000 a kadar olan tüm tam sayılar için sadece hesapladım karekök değerlerini bir döngü içerisinde. time.h içerisinde bulunan clock() fonku ile de geçen süreyi hesapladım Aynı şeyi sqrt() ile de yaptım. Sonuçlar :

    Karekok fonksiyonu : 2093 ms
    sqrt() : 1391 ms

    sürdü işlemler. Sqrt() fark attı :) Üstelik virgülden sonraki kısımları da hesaplıyor. Ama 10 milyon tane sayı için arada 0.7sn lik bir fark pek önemli değil heralde :P




  • Yapay Zeka’dan İlgili Konular
    Daha Fazla Göster
  • Ben bu algoritmayı kullandım. Laptopda denedim ve ilk kısımda sayıyı ayrıştırma işlemi sadece sqrt fonksiyonundan daha fazla zaman almıştı? Masaüstünde ise sizin sonuçlara benzer şeyler buldum. Acaba standart kütüphanenin fonksiyonları assembly mi kullanıyor yoksa ben mi denerken bir yanlış yaptım, bunu bir süre sonra laptoba geri döndüğümde anlayacam artık.
    Cevabınız için teşekkürler:)
  • Sqrt() Fonksiyonu makina dili'ne daha yakın olduğu için daha hızlı sonuç verebilir sonuçta senin yazdığın üst seviye bir dil makina diline çevrilmesi nide hesaba katarsak algoritman harika.
  • Yukarıdaki 81 örneği ile gösterilen metot Newton metodudur ve hesap makineleri onu kullanır. Bilgisayardaki hesap makineleri de buna dahil. Kodla verilen algoritmada değişken tipi uygun şekilde değiştirilerek virgülden sonra da rahatlıkla uygulanabilir. Türkiye'deki Zihinsel Matematik meraklılarının çoğunun kullandığı metot budur. Daha hızlısı var ama deneme yanılma içerdiği için bilgisayara uyarlanamaz.

    KaDoKA adıyla yeni bir metot üzerinde çalışıyorum. İçinde deneme yanılma yok, kesin sonuçlar veriyor. Fakat ara basamaklarda çok büyük sayılarla işlem yapıldığı için insan zihni için henüz uygun değil. Ama bilgisayar için bu hiç sorun olmaz. Üzerinde biraz uğraşarak yazıya dökme niyetindeyim. Burada da paylaşmak isterim.

    Konu hakkında bilgi sahibi olanlar da bilgisayar işlemcisinin bu işlemi nasıl gerçekleştirdiğini paylaşırsa biz de faydalanmış oluruz.



    < Bu mesaj bu kişi tarafından değiştirildi ssakgul -- 28 Aralık 2008; 14:30:24 >




  • Bildiğiniz ve paylaşmak istediğiniz bütün yöntemlere açığım, amacım hızlı algoritmalar yazmak.
    KaDoKA yöntemine gelince, çok büyük sayılar derken integer sınırını aşan şeyler ise, bilgisayar bu işlemi yapmak için tek değişken kullanmayacak. Dizi gibi elemanlar kullanmak zorunda kalırsa fazla zaman alabilir. Ama yine de yönteminizi bitirdiğinizde yazarsanız buraya da, bir algoritma bulmaya çalışırız.
  • Kadoka'yı merak ettim ben de şimdi...
  • kardeş tanımladığın değişkeni int. değilde single olarak veya string olarak tanımla mesela söle.

    bu kodu public class da yaz...

    Private Function karekök(ByVal x As Integer)
    Dim aa As Integer
    aa = Math.Sqrt(x)
    Return aa
    End Function


    sora karekök butonunun içine;

    TextBox2.Text = karekök(TextBox1.Text)
    TextBox2.Visible = True

    bu hesap makınası içindi... hani 3 textbox koyuyodukya ondan dolayı.
  • 32 bitlik bi sayı 36 denemede bulunabiliyor aslında 14 denemede bulunuyor ama sayı gercek sayı olunca en az 36 deneme gerektiriyor işte kod

    int main()
    {
    double sayi,a=32768,m=16384;
    int k;
    printf("sayi giriniz\n");
    scanf("%lf",&sayi);

    for(k=1;k<37;++k){
    if(sayi>a*a){
    printf("%2d. deneme %.7f + %.7f\n",k,a,m);
    a+=m;
    }
    else{
    printf("%2d. deneme %.7f - %.7f\n",k,a,m);
    a-=m;
    }
    m/=2;
    }
    printf("\nsqrt = %f\n",a);
    getch();
    }
    for dongusu ne kadar uzatılırsa hassasiyet okadar artar
    bu kodun çıktısı

    sayi giriniz
    897515462
    1. deneme 32768.0000000 - 16384.0000000
    2. deneme 16384.0000000 + 8192.0000000
    3. deneme 24576.0000000 + 4096.0000000
    4. deneme 28672.0000000 + 2048.0000000
    5. deneme 30720.0000000 - 1024.0000000
    6. deneme 29696.0000000 + 512.0000000
    7. deneme 30208.0000000 - 256.0000000
    8. deneme 29952.0000000 + 128.0000000
    9. deneme 30080.0000000 - 64.0000000
    10. deneme 30016.0000000 - 32.0000000
    11. deneme 29984.0000000 - 16.0000000
    12. deneme 29968.0000000 - 8.0000000
    13. deneme 29960.0000000 - 4.0000000
    14. deneme 29956.0000000 + 2.0000000
    15. deneme 29958.0000000 + 1.0000000
    16. deneme 29959.0000000 - 0.5000000
    17. deneme 29958.5000000 + 0.2500000
    18. deneme 29958.7500000 - 0.1250000
    19. deneme 29958.6250000 - 0.0625000
    20. deneme 29958.5625000 - 0.0312500
    21. deneme 29958.5312500 + 0.0156250
    22. deneme 29958.5468750 + 0.0078125
    23. deneme 29958.5546875 + 0.0039063
    24. deneme 29958.5585938 + 0.0019531
    25. deneme 29958.5605469 + 0.0009766
    26. deneme 29958.5615234 + 0.0004883
    27. deneme 29958.5620117 + 0.0002441
    28. deneme 29958.5622559 + 0.0001221
    29. deneme 29958.5623779 + 0.0000610
    30. deneme 29958.5624390 - 0.0000305
    31. deneme 29958.5624084 + 0.0000153
    32. deneme 29958.5624237 - 0.0000076
    33. deneme 29958.5624161 - 0.0000038
    34. deneme 29958.5624123 + 0.0000019
    35. deneme 29958.5624142 + 0.0000010
    36. deneme 29958.5624151 + 0.0000005

    sqrt = 29958.562416
    bu kod 32 bit icin yazılmıtır yani 4294967296 yukarısı için yanlış sonuc verir

    yine buna benzer bi uygulama bellekteki bizim bilmedigimiz bi sayıyı bulmanın an kolay yolu (benim bildigim) yine 32 bit bir uygulama ve en fazla 32 deneme sonucunda sayı bulunur

    int main()
    {
    unsigned int sayi,k=0,a=2147483648,m=1073741824;
    printf("sayi giriniz\n");
    scanf("%d",&sayi);
    while(sayi!=a){
    ++k;
    if(sayi>a){
    printf("%d. deneme %u + %u\n",k,a,m);
    a+=m;
    }
    else{
    printf("%d. deneme %u - %u\n",k,a,m);
    a-=m;
    }
    m/=2;
    }
    printf("\n sayi=%u\n",a);
    getch();
    }

    bu işlem bitsel olarak ta yapılabilir yine 32 deneme gerektirir
    programın çıktısı

    sayi giriniz
    986546321
    1. deneme 2147483648 - 1073741824
    2. deneme 1073741824 - 536870912
    3. deneme 536870912 + 268435456
    4. deneme 805306368 + 134217728
    5. deneme 939524096 + 67108864
    6. deneme 1006632960 - 33554432
    7. deneme 973078528 + 16777216
    8. deneme 989855744 - 8388608
    9. deneme 981467136 + 4194304
    10. deneme 985661440 + 2097152
    11. deneme 987758592 - 1048576
    12. deneme 986710016 - 524288
    13. deneme 986185728 + 262144
    14. deneme 986447872 + 131072
    15. deneme 986578944 - 65536
    16. deneme 986513408 + 32768
    17. deneme 986546176 + 16384
    18. deneme 986562560 - 8192
    19. deneme 986554368 - 4096
    20. deneme 986550272 - 2048
    21. deneme 986548224 - 1024
    22. deneme 986547200 - 512
    23. deneme 986546688 - 256
    24. deneme 986546432 - 128
    25. deneme 986546304 + 64
    26. deneme 986546368 - 32
    27. deneme 986546336 - 16
    28. deneme 986546320 + 8
    29. deneme 986546328 - 4
    30. deneme 986546324 - 2
    31. deneme 986546322 - 1

    sayi=986546321




  • sqrt hızlıdır çünkü işlemcinin FPU sunu fsqrt assembler komutu ile kullanır.
    fsqrthttp://www.nersc.gov/vendor_docs/ibm/asm/fsqrt.htm
    Sizin yazdığınız metod 8bit gibi küçük çaplı mikrodenetleyicilerde tam sayılar için kullanılabilcek bir metod.
    Kayar nokta ünitesi olmayan cihazlar için sqrt yi kod olarak yazmak istiyorsanız Linux ın çekirdek kodlarına göz atmanızı tavsiye ederim orda FPU emülasyonu için gerekli kodlar mevcut.
    Tam sayılar için kendim yazmakta ısrarcıyım derseniz.Büyük sayılar için çok deneme yapmak yerine sayının büyüklüğüne göre belli başlangıç değerlerini tespit edip o değerlerden denemeye başlayabilirsniz.
    misal
    sayı 100 den büyük ise karekök 10 dan küçük olamaz o zaman başlangıç değeri 10 olmalıdır gibi.




  • 
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.