Sunum yükleniyor. Lütfen bekleyiniz

Sunum yükleniyor. Lütfen bekleyiniz

Ses Kontrol Metodlar ile ilgili son birkaç söz Tekrar: Programlama için başlıca 3 model.

Benzer bir sunumlar


... konulu sunumlar: "Ses Kontrol Metodlar ile ilgili son birkaç söz Tekrar: Programlama için başlıca 3 model."— Sunum transkripti:

1

2 Ses Kontrol

3 Metodlar ile ilgili son birkaç söz

4 Tekrar: Programlama için başlıca 3 model

5 Java Metodları Java ‘da hem fonksiyonlar hem de prosedürler için metod adı altında tek bir yapı mevcuttur: prosedür olarak kullanıldığında metod isminin hemen önüne geri dönüş değeri olarak “void” ifadesi yazılır. public void printHelloWorld( ) { System.out.println(“Hello World!”); } // of printHelloWorld Not: Bütün metodlarda parametre almasa dahi çift parantez kullanmak zorunludur! Hızlı Tekrar

6 fonksiyon olarak kullanıldığında metod isminin hemen önüne gerekli olan geri dönüş değerinin türü yazılır. public float average (float fNum1, float fNum2, float fNum3) { float fReturnVal; fReturnVal = (fNum1 + fNum2 + fNum3)/ 3; return (fReturnVal); } // of average Java Metodları Hızlı Tekrar

7 Metodların İmzaları “Metodun imzası, metodun adı, ve aldığı parametre sayısı ve türlerinden oluşur. Herhangi bir sınıf aynı imzaya sahip iki metod tanımlayamaz, tanımlasa bile derleme zamanı hatası oluşur.” Metod overloading adını verdiğimiz olay, aynı isme sahip metodların farklı imzalara sahip olmasıyla oluşur. public int getCube(int iNum){ return iNum*iNum*iNum; } public int getCube(float fNum){ return (int)(fNum*fNum*fNum); } public int getCube(double dNum){ return (int) (dNum*dNum*dNum); } Hızlı Tekrar

8 ParametrelerParametreler Unlike Pseudocode, Java only has “in” parameters.Unlike Pseudocode, Java only has “in” parameters. Thus no need to declare in, in/out or out ‘cause they’re all INThus no need to declare in, in/out or out ‘cause they’re all IN Parametreler de tıpkı değişkenler gibi tanımlanır:Parametreler de tıpkı değişkenler gibi tanımlanır: public void demo(int i, float x) public void demo(int i, float x) Nesneleri tartışırken parametreler hakkında daha çok şey öğreneceğiz.Nesneleri tartışırken parametreler hakkında daha çok şey öğreneceğiz. Unlike Pseudocode, Java only has “in” parameters.Unlike Pseudocode, Java only has “in” parameters. Thus no need to declare in, in/out or out ‘cause they’re all INThus no need to declare in, in/out or out ‘cause they’re all IN Parametreler de tıpkı değişkenler gibi tanımlanır:Parametreler de tıpkı değişkenler gibi tanımlanır: public void demo(int i, float x) public void demo(int i, float x) Nesneleri tartışırken parametreler hakkında daha çok şey öğreneceğiz.Nesneleri tartışırken parametreler hakkında daha çok şey öğreneceğiz.

9 Metodlar nerede durur? Methodlar, sınıflara ait üyeler gibi sınıfların içinde tutulurlar. Sınıf ve nesne oluşturmayı öğrenirken daha ayrıntılı göreceğiz ancak aşağıda kısaca bir örnek verelim: class zippy { int pin; public String yow() { // some code } Hızlı Tekrar

10 Sorular?

11 Yineleme (İterasyon)

12 Java Temelleri: İterasyon YapıIarı Aslında temelde, tüm iterasyon türlerinde kullanılan tek bir iterasyon yapısı mevcuttur. Geçen dönem dikkat ettiyseniz üç çeşit döngüden bahsetmiştik: Sentinal Loops Test-Last Loop N-and-a-half Loops Geçen dönem dikkat ettiyseniz üç çeşit döngüden bahsetmiştik: Sentinal Loops Test-Last Loop N-and-a-half Loops

13 Java Temelleri: İterasyon Yapıları Biraz önce de söylediğimiz gibi temelde, tüm iterasyon türlerinde kullanılan tek bir iterasyon yapısı mevcuttur. Ancak, bu temelde böyledir. Java ‘da diğer birçok programlama dilinde olduğu gibi herşeye uyan esnek tek bir yapı mevcut değildir. Bunun yerine, Java herbiri belirli bir amaca uygun olmak üzere 3 çeşit döngü yapısı sunar. Tek bir döngü yapısına alışıp onu heryerde kullanmaya çalışmayın. Bu yapıları akıllıca kullanabilmek için bu yapıların sadece nasıl çalıştığını değil en iyi nerede kullanılabileceklerini de bilmeniz gerekir...

14 Herhangi bir işi tekrar ederken insanlar doğal olarak aşağıdaki yöntemi tercih eder: değeri elde et, daha sonra bu değeri işle While döngüsü ise doğal olmayan yöntemi tercih eder: Döngüye girmeden önce döngünün kontrol değişkeninin değerini elde et; sonra, döngüye gir, ilk önce işlemleri yap, daha sonra diğer adımlara geç Java İterasyon Yapıları: “While Döngüleri”

15 Doğal olmayan? while(Benim sokağıma gelmediğin sürece) { Düz yürümeyi sürdür } Sağa dön

16 Java örneği: while (şart) { } Pseudocode: döngü döngüden çık eğerki sağlamıyorsa (şart) döngü sonu Java İterasyon Yapıları: “While Döngüleri” Gözcü:Sentinal

17 Java örneği: do { deyim 1;... deyim N; } while (şart); Java İterasyon Yapıları: “Do While Döngüleri” Pseudocode: döngü deyim 1... deyim N döngüden çık eğerki sağlamıyorsa (şart) döngü sonu Sonra Test Et:Test Last

18 Pseudocode: Num türünden i diye bir değişken tanımla i ‘ye 0 değerini ata döngü eğer (i >=10) ise çık değilse i ‘nin içeriğini 1 artır döngü sonu Java İterasyon Yapıları: “For Döngüleri” Java örneği: int i; for (i=0; i<10; i++) { } Java sentaksı: for ( ; ; )

19 Aşağıda for döngüsü ile while döngüsü aynı işi yapmaktadır. i = 0; while (i < 10) { System.out.println(i);i++; } i++ for(i = 0; i < 10; i++) { System.out.println(i); } Bu örnek, size for yapısını daha iyi anlamanıza yardımcı olacaktır.

20 For döngüleri ile ilgili genel hatalar: Java İterasyon Yapıları: “For Döngüleri” for (i=0; i<N; i++) ; { … } for (int i=0; i<N; i++){…} -- yukarıda değişken tanımlaması döngü imza yapısının içinde tanımlanmış... --değişkene bu döngü imza yapısının dışında ihtiyaç olabilir, bu yüzden bu tür tanımlamalardan kaçının. --Yukarıdaki hatada for döngü yapısı dikkate alınmadan liste işaretleri arasında kalan işlemler sadece 1 kez yapılır. ; işaretinden dolayı tekrarlama söz konusu değildir.

21 Çokça Yapılan Bir Hata public class Forex { static int i = 42; public static void main(String args[]) { for(int i=0; i < 5; i++) { System.out.println(i); } System.out.println(i); }

22 Çıktı 0 1 2 3 4 42

23 -- “kontrol değişkeni” olarak ifade edilen değişkeninin değeri, döngünün devam mı edeceği yoksa sonlanacağına mı karar vermek amacıyla kontrol edilir. --Örneğin, aşağıdaki thisVar değişkeni: while (thisVar < = SOME_CONSTANT) --Hangi durumda hangi döngü yapısını kullanacağınıza karar vermek için öncelikle şu soruyu kendinize sorun: “kontrol değişkeninin değeri nereden gelmektedir?” Java İterasyon Yapıları: Hangisini Ne Zaman ? Sor: Bu kontrol değeri sadece döngü sayısını mı ifade ediyor? Bu değer, döngü yapısının hesaplaması gereken bir şey mi? Yoksa bu değer herhangi bir yerde mevcut ta döngü onu oradan elde mi ediyor?

24 for döngüsü: kontrol değişkeni sadece döngü sayısını ifade ettiği zamanlarda kullanılır. örnek: “100 adet sayı girişi alıp, işleyecek bir döngü oluşturun.” while döngüsü: bu değer herhangi bir yerde mevcut ve döngü onu bir yerlerden elde ettiği durumlarda kullanılır. örnek: “klavyeden 100 değeri girilene kadar devamlı olarak sayı girişi alan ve bunları işleyen bir döngü oluşturun” do-while döngüsü: bu değerin döngünün bizzat kendisi tarafından hesaplanması gereken durumlarda kullanılır. örnek: “klavyeden, girilen sayıların toplamı 100 oluncaya kadar giriş alan döngü oluşturun” Java İterasyon Yapıları: Hangisini Ne Zaman ?

25 Hangi yapıyı kullanırdınız eğer ki... Java İterasyon Yapıları:Tekrar Java İterasyon Yapıları: Tekrar Bir dizi işlemi N kez gerçekleştirmek için... Ne kadar uzunlukta olduğunu bilmediğiniz bir liste üzerinde dolaşıyorsanız ve aradığınız değeri bulunca duracaksanız... Bir dizi işlemi en az bir kere olmak üzere, en çok ne kadar çalıştırılacağını ise henüz bilmiyorsanız (hesaplanacak)...

26 İterasyon (Tekrar) –Üç çeşit iterasyon vardır: –for (...;...;...) {...} döngüleri –Sabit sayıda yineleme yapılır –while (...) {...} döngüleri –Döngü kontrol değeri daha önceden hesaplanmış –do {...} while (...) döngüleri –Döngü kontrol değeri döngü içerisinde hesaplanmaktadır

27 Sorular?

28 Temel veri türlerinden Diziler Anafikir: Daha önce öğrendiklerinize benzer Yazılımda bazı farklılıklar vardır Java ‘da dizi bildirimi: [ ] = new [ ]; örnek: 10 adet tamsayı türündeki notu tutmak için tamsayı türünden 10 elemanlı bir dizi oluşturalım: int[ ] notDizisi = new int[10]; Dizi bildirim hatası: köşeli parantez yerine normal parantez kullanmak: int[ ] iGradeArray = new int(10);

29 Detaylar Sentaks biraz garip gelebilir çünkü diziler de birer nesnedir. Nesneleri anlatmaya başlayınca detaylı olarak inceleyeceğiz... int[ ] iGradeArray = new int[10]; int iGradeArray[ ] = new int[10];

30 Örnek: 10 adet tamsayı türündeki notu tutmak için tamsayı türünden iNotDizisi adında 10 elemanlı bir dizi oluşturalım dizinin bütün değerlerine 0 değerini atayalım int[ ] iNotDizisi = new int[10]; int i; /* dizi işlemlerinde indis yani kontrol değişkeni olarak i,j,k gibi geleneksel olarak herkes tarafından kullanılan ve tanınan değiken isimleri kullanın. */ for (i=0; i < iNotDizisi.length; i++) { iNotDizisi[i] = 0; } // for döngüsü Not: Diziler kendi uzunluklarını bilirler length bir özelliktir, metod değil Dizi uzunlukları sabittir, bildirim yapıldıktan sonra bir daha değiştirilemez. Bütün diziler nesnedir, bu nedenle bir referans değişkeni bişldirimi yapmalı, nesneyi oluşturmalı ve ilk değerini atamalısınız(declare a reference, instantiate, initialize)Diziler Güzel düşünce! Dizinin boyutunu değiştirdiğinizde, sadece for imza yapısının içini değiştirmeniz yeterli.

31 Notlar: Dizi indisi her zaman 0 ‘dan başlar 1 ‘den değil Öyleyse, length yani dizi uzunluk değeri indisin maksimum alacağı değerden sayısal olarak 1 fazladır Bu nedenle, eğer aşağıdaki gibi yaparsanız hata yaparsınız: int[ ] iGradeArray = new int[10]; int i; for (i=1; i <= iGradeArray.length; i++) { iGradeArray[i] = 0; } // for loop Yukarıdaki program kodunda dizinin 1 ’den 10 ’a kadar olan elemanlarına erişilmeye çalışılıyor Ancak dizinin indis numaraları 0..9 aralığındadır Öyleyse: dizini ilk elemanı olan 0 indis olanı kaçırıyor ve dizinin 10 indis numaralı elemanına erişmeye çalışıyorki ne böyle bir indis mevcut ne de diziye ait böyle bir alan. Diziler

32 Sorular?

33 Örnek Quiz Sorusu Tamsayı türünden bir dizinin elemanları arasında en yüksek değere sahip olanın indis numarasını geri döndüren programı yazınız. Aşağıdaki kodu kullanın: public int enBuyugunIndisiniDondur(int[ ] iDizi){ /* Kodunuzu buraya yazın*/ }

34 Örnek Quiz Sorusu public int enBuyugunIndisiniDondur(int[ ] iDizi){ int enBuyuk = -9999; int i; for (i = 0; i < iDizi.length; i++) { if (enBuyuk < iDizi[sayac]) enBuyuk = iDizi[i]; } return enBuyuk; } // enBuyugunIndisiniDondur metodunun sonu Çalışır mı?

35 Örnek Quiz Sorusu Eğer dizinin bütün değerleri -9999 ‘dan küçükse ne olacak? public int enBuyugunIndisiniDondur(int[ ] iDizi){ int enBuyuk = -9999; int i; for (i = 0; i < iDizi.length; i++) { if (enBuyuk < iDizi[sayac]) enBuyuk = iDizi[i]; } return enBuyuk; } // enBuyugunIndisiniDondur metodunun sonu

36 Örnek Quiz Sorusu Peki bu nasıl? public int enBuyugunIndisiniDondur(int[ ] iDizi){ int enBuyuk = iArray[0]; int i; for (i = 0; i < iDizi.length; i++) { if (enBuyuk < iDizi[sayac]) enBuyuk = iDizi[i]; } return enBuyuk; } // enBuyugunIndisiniDondur metodunun sonu

37 Örnek Quiz Sorusu i sayaç değerini neden daha önceleri olduğu gibi 0 ‘dan değil de 1 ‘den başlattık? public int enBuyugunIndisiniDondur(int[ ] iDizi){ int enBuyuk = iArray[0]; int i; for (i = 1; i < iDizi.length; i++) { if (enBuyuk < iDizi[sayac]) enBuyuk = iDizi[i]; } return enBuyuk; } // enBuyugunIndisiniDondur metodunun sonu

38 Örnek Quiz Sorusu Bu haliyle mükemmel! ??? public int enBuyugunIndisiniDondur(int[ ] iDizi){ int enBuyuk = iArray[0]; int i; for (i = 1; i < iDizi.length; i++) { if (enBuyuk < iDizi[sayac]) enBuyuk = iDizi[i]; } return enBuyuk; } // enBuyugunIndisiniDondur metodunun sonu

39 Örnek Quiz Sorusu Tamsayı türünden bir dizinin elemanları arasında en yükse değere sahip olanın indis numarasını geri döndüren programı yazınız.. Dikkat! public int enBuyugunIndisiniDondur(int[ ] iDizi){ int enBuyuk = iArray[0]; int i; for (i = 1; i < iDizi.length; i++) { if (enBuyuk < iDizi[sayac]) enBuyuk = iDizi[i]; } return enBuyuk; } // enBuyugunIndisiniDondur metodunun sonu

40 Örnek Quiz Sorusu Öyleyse çözüm nedir? Bu, kendi kendinize çözebileceğiniz güzel bir problem. Biz en büyük değeri değil, en büyk değerin indisini öğrenmek istiyoruz.

41 Aldığımız dersler Soruyu iyi oku. Alışkanlıklara kapılma (örneğin bütün döngüler 0 ‘dan başlamalı gibi...). Varsayımlar yapma (örneğin, -9999 iyi bir değer değildir). Kodunuzu iyi inceleyin; basit >, < hatalarınızın olup olmadığını araştırın.

42 Sorular?

43 Özyineleme(Recursion) Sınıflar ve Nesneler Yapıcılar Nesnelere Referanslar Referanslar Parametreler Gideceğimiz yol Bugün

44 Soru Burada kaç kişi özyinelemeyi sevmiyor? Neden? Söz veriyorum: Bu dersin sonunda diyeceksiniz ki: “Özyineleme dünyamı değiştirdi”

45 Özyineleme (Recursion) Diyelim ki 2 tavşanı bir kafese koydunuz. Ne olacak? Bir aile

46 Eğer tavşanlar 2 ayda olgunlaşıyorlarsa, 2 ay içinde elinizde üreyebilecek 1 çift ile üremeye müsait olmayan başka bir çift tavşan olacaktır. İki ay sonra... ilk rabbits yeni tavşanlar

47 1 aylık 0 aylık Gelecek ay, yeni bir çift elde edersiniz... Bu böylece devam eder

48 Farzedelim ki Tavşanlar hep iki adet yavru meydana getiriyorlar ve bunların biri erkek diğeri de dişi Tavşanlar hep 2 ay sonunda olgunlağa ulaşıyorlar Hiçbir tavşan ölmüyor Bir sene sonunda kaç tavşanımız olur? 11 22 33

49 Yaban tavşanının çoğalma hikayesi Başlangıç 5. Ay sonunda 1. Ay sonunda 2. Ay sonunda 3. Ay sonunda 4. Ay sonunda = bir e/d çift Anahtar

50 Tavşan çiftleri 1 2 3 4 5 6 7 8 9 10 11 12 AyÜretkenÜretken olmayanToplam 0 1 1 2 3 5 8 13 21 34 55 89 0 1 1 2 3 5 8 13 21 34 55 11 1 2 3 5 8 13 21 34 55 89 144 Modeli görebildiniz mi?

51 Başka bir örnek verelim Tavşanlar yerine geometriyi kullanalım. Kenar uzunluğu 1 olan bir adet kare çizin. 90 derece çevirerek bu kareye aynısından 1 tane daha ekleyin. Tekrar 90 derece döndürerek bu sefer 2 uzunluğunda bir kare ekleyin. Tekrar, döndürün ve bu sefer 3 uzunluğunda bir kare ekleyin ve böyle artarak devam edin. Oluşan seri: 1, 1, 2, 3, 5, 8, 13, 21,..., Ne görüyorsunuz?

52 1

53 1

54 2

55 3

56 5

57 8

58 13

59 21

60 11 2 3 5 8 13 21

61 Tanıdık geldi mi?

62 Sadece tavşanlar ile ilgili değilmiş.

63 Gerçek karşınızda

64 Modele bakın? 1 2 3 4 5 6 7 8 9 10 11 12 AyÜretkenÜretken olmayanToplam 0 1 1 2 3 5 8 13 21 34 55 89 0 1 1 2 3 5 8 13 21 34 55 11 1 2 3 5 8 13 21 34 55 89 144 Aşağıdaki serinin nasıl arttığını bulmak için çok çaba harcadık: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,..., Bu modeli gerçek hayatta bir çok yerde görebilirsiniz: istiridye kabuğu, çam ağaçlarında, arı kovanlarında, vb... Bu bir Fibonacci Serisi.

65 Formül Verilen seri: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,..., Herhangi bir sayı (n) için yukarıdaki seriyi formülize edebilir miyiz? Yanda görülen kişi yapmış: Jacques Binet (1786-1856) 1+ 1- 55 2 2 - nn Fib(n) = Dürüst olmak gerekirse biz onun kadar zeki değiliz. Ama biz bu fomülü kodlayabiliriz.

66 Eğer formülü bulamazsak ne yapacağız? Farzedin ki aşağıdaki formülü bilmiyorsunuz: 1+ 1- 55 2 2 - nn Fib(n) = Matematik dersi alabilirsiniz ya da aşağıdaki metodu uygulayabilirsiniz: Fib(n) = Fib(n-1) + Fib(n-2), Fib(0) = 0; Fib(1) = 1; (Herhangi bir noktadaki değer kendisinden önce ardışık gelen iki değerin toplamına eşittir.) Hangisini kodlamayı tercih ederdiniz? Bazı nedenlerden dolayı formülü elde edemeyebilirsiniz, ve bu durumda özyineleme (recursion ) tek seçeneğinizdir.

67 Özyinelemeli (Recursive) Fibonacci Fib(n) = Fib(n-1) + Fib(n-2), Fib(0) = 0; Fib(1) = 1; Genel Kural: Birkaç şey söyleyebiliriz bunun hakkında: Özyinelemeli olarak tanımlanmış (güzel). Durma şartı var (Yakaladık!) Hesaplanabilir (toplama). 1 2 3

68 Fibonacci serisini programlama public class FibTest { public static int fib (int num) { }// FibTest Başlangıç için ne biliyoruz? Herhangi bir noktadaki sayının Fibonacci değerini bulmak için bir metoda ihtiyacımız var.. Bu metod, int (tamsayı) türünden bir parametre almalı ve geriye gene int (tamsayı) türünden bir değer döndürmelidir.

69 Fibonacci serisini programlama public class FibTest { public static int fib (int num) { if (num == 0) return 0; }// FibTest Özyinelemeli bir metod ile ilgili ilk yapmamız gereken şey nedir? Nasıl sonlanacağını planlamamız gerekir. Fibonacci serisi için özel bir durumu biliyoruz: F(0) = 0

70 Fibonacci serisini programlama public class FibTest { public static int fib (int num) { if (num == 0) return 0; else if (num == 1) return 1; }// FibTest Sonlanmasını sağlamak için ikinci bir özel durumu daha biliyoruz: F(1) = 1.

71 Fibonacci serisini programlama public class FibTest { public static int fib (int num) { if (num == 0) return 0; else if (num == 1) return 1; else return fib(num-1) + fib(num-2); } }// FibTest Formülün son kısmı sadece: F(n) = F(n-1) + F(n-2)

72 Fibonacci serisini programlama public class FibTest { public static int fib (int num) { if (num == 0) return 0; else if (num == 1) return 1; else return fib(num-1) + fib(num-2); } }// FibTest Bu güvenli mi? Eğer metoda parametre olarak 0 değeri gönderilirse ne olur? Ya da 1 ?

73 Fibonacci serisini programlama public class FibTest { public static int fib (int num) { if (num == 0) return 0; else if (num == 1) return 1; else return fib(num-1) + fib(num-2); } public static void main(String[] args) { for (int i=0; i < 10; i++) System.out.println (fib(i)); } }// FibTest Metodu test etmek için bir main bloğu yazmak sizin sorumluluğunuz.

74 Fibonacci serisini programlama public class FibTest { public static int fib (int num) { if (num == 0) return 0; else if (num == 1) return 1; else return fib(num-1) + fib(num-2); } public static void main(String[] args) { for (int i=0; i < 10; i++) System.out.println (fib(i)); } }// FibTest İşimiz bitti mi? Peki negatif sayılar ne olacak? Yaptığımızdan daha fazlası gerekli?

75 Tekrar Şimdiye kadar özyineleme hakkında ne gördük hatırlayalım: 1) Özyineleme bütün doğada mevcuttur. 2) Formül ezberlemekten daha kolaydır. Her problemin bir formülü olmayabilir, ancak her problem, küçük, tekrarlayan adımlar serisi olarak ifade edilebilir.. 3) Özyinelemeli bir işlemde her adım küçük ve hesaplanabilir olmalıdır. 4) Kesinlikle sonlandırıcı bir şarta sahip olmalı.

76 Dürüst olmak gerekirse 1. Özyinelemeyi kolay anlatabilmek amacıyla genelde faktöriyel ve Fibonacci serisi örnekleri verilir. 2. Gerçekte Fibonacci serisini özyineleme yöntemiyle hesaplamak hiç te iyi bir yöntem değildir, ayrıca faktöriyel hesaplarken de özyineleme kullanmanın büyük bir avantajı yoktur. 3. Öyleyse, özyineleme ile ilgili bu kadar gürültü patırtı neden? 4. Özyineleme en çok, özyinelemeli olarak tanımlanmış binary tree dediğimiz veri yapılarında kullanılmak üzere yazılan algoritmalar için faydalıdır. Normal iterasyona göre çok daha kolaydır. 5. Özyineleme, divide & conquer türündeki algoritmalar için mükemmeldir.

77 Bir örnek daha Aşağıdaki formülü çözmek için bir metod yazalım: Pow(x, y) = x y Diğer bir deyişle, metod kendisine parametre olarak verilen sayılardan birini diğerinin üstü olarak hesaplayacaktır: public static double pow (double value, int exponent);

78 Metodun Planlanması Formülümüz, Fibonacci serisinde olduğu gibi nihai sonuç değildir. Pow(x, y) = x y Sonlandırıcı koşulları unutmayalım... Bildiğimiz gibi: x 1 = x; x 0 = 1; Öyleyse bunları sonlandırıcı koşul olarak kullanabiliriz.

79 1. Deneme public static double pow(double value, int exponent){ if (exponent == 0) return 1D; Her zaman için sonlandırıcı bir koşul ile başlayın. Biliyoruz ki, herhangi bir sayının 0. kuvvetini alırsak sonuç sıfırdır.

80 1. Deneme public static double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value;... Ve herhangi bir sayının 1. kuvvetini alırsak sonuç sayının kendisidir.

81 1. Deneme public static double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else return value * pow (value, exponent--); } Diğer bütün değerler için sonuç olarak üst olarak alınan sayı ile özyineleme fonksiyonunun tekrar çağrılarak sonucunun çarpımı geri döndürülür. Sayaç olarak ta, üst (kuvvet) olarak kullanılacak sayı kullanılır. Bu sayı 0 olana kadar özyineleme devam eder. Yani, metod kendi kendini çağırır.Böylece, aşağıdaki hesaplama ortaya çıkar: 2 6 = 2*2*2*2*2*2

82 1. Deneme public static double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else return value * pow (value, exponent--); } Fakat, yukarıdaki kodu çalıştırdığımızda kötü şeyler olur. Program çöker ve yığın taşması hatasına neden olur. Peki bu sorunu nasıl çözeriz?

83 1. Deneme public static double pow(double value, int exponent){ if (bDEBUG) System.out.println (“Entering with: “ + value + “, and exp: “ + exponent); if (exponent == 0) return 1D; else if (exponent == 1) return value; else { return value * pow (value, exponent--); }

84 1. Deneme public static double pow(double value, int exponent){ if (bDEBUG) System.out.println (“Entering with: “ + value + “, and exp: “ + exponent); if (exponent == 0) return 1D; else if (exponent == 1) return value; else { return value * pow (value, exponent--); } Hata ayıklama mesajının söylediğine göre sayacımızı azaltmamışız. Açıkça görülüyor ki, “exponent--” ifadesi, metod özyinelemeli olarak kendini çağırmadan önce değerlendirmeye alınmamış. Bundan da anlaşılıyor ki, “ -- ” kısayol operatörü problem çıkarıyor. DOH!

85 1. Deneme public static double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else { exponent = exponent - 1; return value * pow (value, exponent); } Karar verdik ki, fazladan 1 satır yazmak sebebi güç farkedilen böyle bir hatayla uğraşmaktan çok daha az vakit alıyor. Şimdi herşey çalışıyor...

86 “ Özyinelemeyi kullanmak zorunda mıyım ?” public static double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else { exponent = exponent - 1; return value * pow (value, exponent); } Kaç kişi bu işlemi “for” veya diğer iteratif döngülerle yapmayı tercih eder? Kaç kişi bu işlemi özyinelemeli olarak yapmanın iteratife göre daha hızlı olduğunu düşünüyor?

87 Dikkat ! 2 8 = 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 Ancak biz bu çözümü iki eşit parçaya bölerek ifade edebiliriz: 2 8 = 2 4 * 2 4 ve 2 4 = 2 2 * 2 2 ve 2 2 = 2 1 * 2 1 ve herhangi bir sayının 1. kuvveti kendisidir.

88 İşin güzel tarafı burada... 2 8 = 2 4 * 2 4 İkisi de aynı olduğu için, her ikisini de hesaplamıyoruz!

89 Evvet! Öyleyse, işin püf noktası, 2 8 ifadesinin iki parçaya ayrılıp sonucun iki defa kullanılmasıdır. Öyleyse, sadece 3 adet çarpma işlemi yapılıyor: 2 8 = 2 4 * 2 4 2 4 = 2 2 * 2 2 2 2 = 2 1 * 2 1

90 “Ama bekle," dediğinizi duyar gibiyim! 2 ‘nin kuvveti olarak aldığımız sayı çift sayıydı. Peki ya, tek sayı alırsak ne olur? Tek olanları şu şekilde yaparız: 2 tek = 2 * 2 (tek-1)

91 “Ama bekle," dediğinizi duyar gibiyim! Peki öyleyse, 2 21 ‘i hesaplayalım 2 21 = 2 * 2 20 (Tek sayı hilesi) 2 20 = 2 10 * 2 10 2 10 = 2 5 * 2 5 2 5 = 2 * 2 4 2 4 = 2 2 * 2 2 2 2 = 2 1 * 2 1

92 “Ama bekle," dediğinizi duyar gibiyim! 2 21 = 2 * 2 20 2 20 = 2 10 * 2 10 2 10 = 2 5 * 2 5 2 5 = 2 * 2 4 2 4 = 2 2 * 2 2 2 2 = 2 1 * 2 1 Görüldüğü üzere, 20 kez çarpım işlemi yapmak yerine 6 kerede sonuca ulaşıyoruz. Kuvvet (üst) sayısı büyüdükçe durum daha da dramatik bir hal almaktadır.

93 Özyinelemenin mantığı Eğer üst çift ise, iki parçaya ayırıp işleriz. Eğer üst tek ise, 1 çıkarır daha sonra kalan kısmı ikiye ayırıp işleriz. Ama üstten bir çıkardığımız için en sonunda 1 adet çarpma işlemi daha yapmayı unutmayın. İşlemi formülize etmeye başlayalım: e == 0, Pow(x, e) = 1 e == 1, Pow(x, e) = x e çift ise, Pow(x, e) = Pow(x, e/2) * Pow(x,e/2) e>1 ve tek ise, Pow(x, e) = x * Pow(x, e-1)

94 2. Çözüm public static double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; } İlkinde olduğu gibi aynı sonlandırıcı koşulları kullanıyoruz.

95 2. Çözüm public static double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { } Bu ifade, sayının çift olup olmadığının kontrolünü yapmaktadır.

96 2. çözüm public static double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { } public static int isOdd(int num){ if (num==0) return 1; else return isEven(num-1); } public static int isEven(int num){ if (num==0) return 0; else return isOdd(num-1); } mod operatörünü sevmediyseniz alışmaya çalışın. Alternatifi hiç te akıllıca olmayan yandaki gibi özyinelemeli bir yöntem:

97 2. çözüm public static double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { } public static int isOdd(int num){ if (num==0) return 1; else return isEven(num-1); } public static int isEven(int num){ if (num==0) return 0; else return isOdd(num-1); } mod operatörü daha güzel görünmeye başladı. Yukarıdaki ifadede sayının ikiye bölündüğünde kalanını bulmaktadır.

98 2. çözüm public static double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; } Daha sonra üst olarak alınan sayıyı (exponent) ikiye bölüyoruz.

99 2. çözüm public static double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; double half = pow (value, exponent); } Yarısını özyinelemeli olarak hesaplamaya devam ediyoruz.

100 2. çözüm public static double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; double half = pow (value, exponent); return half * half; } Sonuç olarak, iki yarımın çarpımı geri döndürüyoruz.

101 2. çözüm public static double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; double half = pow (value, exponent); return half * half; } else { exponent = exponent - 1; } Eğer üst tek ise, 1 azaltıyoruz...

102 2. çözüm public static double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; int half = pow (value, exponent); return half * half; } else { exponent = exponent - 1; double oneless = pow (value, exponent); } 1 azalttıktan üst şimdi çift oldu ve ilk durumdaki hesaplamayı uygulamaya koyacağız.

103 2. çözüm public static double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; int half = pow (value, exponent); return half * half; } else { exponent = exponent - 1; double oneless = pow (value, exponent); return oneless * value; } Sonucu, taban olarak kullanılan sayı ile çarpmayı unutmayın, çünkü üstü, tek olduğu için 1 azalttık.

104 Özyineleme mi İterasyon mu? Eğer iteratif çözümü tercih ederseniz algortimanızın karmaşıklığı O(N) olur. Gerçek dünyada bu yöntemi kullanırsanız kovulursunuz. Eğer özyineleme kullanırsanız, algoritmanızın karmaşıklığı O(log2n) olur. Bunun için terfi bile alabilirsiniz.

105 DUR Çok kritik bir nokta geliyor

106 Sorular?


"Ses Kontrol Metodlar ile ilgili son birkaç söz Tekrar: Programlama için başlıca 3 model." indir ppt

Benzer bir sunumlar


Google Reklamları