Sayıların gizemli dünyasında en ünlü dizilerden biri olan Fibonacci, sadece doğada değil, bilgisayar bilimlerinde de karşımıza çıkar. Peki, Python ile bu diziyi üretmek ne kadar kolay ve ne kadar maliyetlidir? Gelin, özyinelemeli (recursive) bir yaklaşımla Fibonacci dizisini nasıl oluşturabileceğimizi ve bu yöntemin performans üzerindeki etkilerini inceleyelim.
Fibonacci Dizisi ve Python ile Hesaplama
Fibonacci dizisi, her sayının kendisinden önceki iki sayının toplamı olduğu basit ama büyüleyici bir matematiksel dizidir. Dizi 0 ve 1 ile başlar: 0, 1, 1, 2, 3, 5, 8, 13, 21… ve böylece sonsuza kadar gider.
Bu projede, Fibonacci dizisini üretmek için Python’ın en güçlü kavramlarından biri olan özyineleme (recursion) yöntemini kullandık. Özyineleme, bir fonksiyonun kendi kendisini çağırması durumudur. Fibonacci’nin tanımı zaten özyinelemeli olduğu için (f(n) = f(n-1) + f(n-2)), bu yöntem kodu oldukça sade ve okunabilir kılar.
Kodun Anatomisi
Projenin kalbinde yer alan fib(n) fonksiyonu, Fibonacci mantığını en saf haliyle uygular. İşte kodun kilit noktaları:
def fib(n):
# Base Case: n 2'den küçükse (0 veya 1), direkt n değerini döndür
if n < 2:
return n
# Recursive Step: n'den önceki iki sayının toplamını hesapla
return fib(n - 1) + fib(n - 2)
Bu yapıda iki kritik bölüm vardır:
- Durdurma Koşulu (Base Case): Eğer bu koşul olmasaydı, fonksiyon sonsuza kadar kendini çağırır ve program “Stack Overflow” hatasıyla çökerdi.
- Özyineleme Adımı: Fonksiyon, karmaşık bir problemi daha küçük alt problemlere bölerek çözer.
Ayrıca, her bir hesaplamanın ne kadar sürdüğünü görmek için time.perf_counter() fonksiyonu ile yüksek hassasiyetli zaman ölçümleri gerçekleştirdik.
Nasıl Çalıştırılır?
Proje, Ubuntu 24.04 üzerinde Python 3.12 ile geliştirilmiştir. Çalıştırmak için şu adımları izleyebilirsin:
- Proje klasörüne git:
cd 04_fibonacci
- Script’i çalıştır:
python3 fibonacci.py
Çıktı Analizi:
Program çalıştığında her sayının indeksini, değerini ve hesaplanma süresini (milisaniye cinsinden) göreceksiniz. İlk sayılar anında hesaplanırken, indeks arttıkça (özellikle 30’dan sonra) sürenin nasıl hızla arttığını fark edeceksiniz.
Ne Öğrendik?
Bu çalışma bize şu önemli dersleri verdi:
- Özyineleme (Recursion): Karmaşık matematiksel tanımları koda dökmenin en zarif yolu olduğunu gördük.
- Zaman Karmaşıklığı: Naif özyineleme yönteminin $O(2^n)$ gibi üstel (exponential) bir zaman karmaşıklığına sahip olduğunu, yani girdi arttıkça işlem süresinin korkutucu şekilde arttığını gözlemledik.
- Performans Ölçümü:
perf_counterile kodun gerçek dünyadaki hızını nasıl ölçeceğimizi öğrendik.
Kaynaklar ve Sonraki Adımlar
Eğer hesaplama süreleri sizi rahatsız ettiyse, bir sonraki adım olarak Memoization (Ezberleme) tekniğini araştırmanızı öneririm. functools.lru_cache dekoratörü ile aynı hesaplamaların tekrar tekrar yapılmasını önleyebilir ve performansı inanılmaz ölçüde artırabilirsiniz.
Ahmet Aksoy
Not: Bu yazıda incelediğimiz kodu ve benzer projelerin kaynak kodlarını https://github.com/ahmetax/practical-python-examples adresinde bulabilirsiniz.