1.3. Matematiksel Fonksiyonlar

Kayıt Tarihi:

Son Güncelleme:

Özet:

Daha karmaşık matematiksel hesaplamalar için math gibi modülleri kullanmaya ihtiyacımız olur. Üstel, trigonometrik, logaritmik ve benzeri fonksiyonlar bu gibi modüller içindedir.

Anahtar Kelimeler: cmath · decimal · import · kompleks fonksiyonlar · kompleks sayılar · math · modül · scipy · yuvarlama hatası

Şimdi biraz daha karmaşık hesaplamalar yapalım. Varsayalım ki bir top belirli bir ilk hızla yerden fırlatılıyor ve topun verilen bir $y=y_1$ konumuna ne kadar zamanda ulaşacağını hesaplamamız isteniyor. Bu problemi çözmek için $$y_1=v_0t-\frac{1}{2}gt^2$$ formülünde $t$ değişkenini çözmemiz gerekiyor. Bunun için denklemi $$\frac{1}{2}gt^2-v_0t+y_1=0$$ biçiminde yazalım, bu denklem $t$'nin ikinci dereceden cebirsel bir denklemidir ve çözümü $$t_1=\frac{v_0-\sqrt{v_0^2-2gy_1}}{g}\quad\text{ve}\quad t_2=\frac{v_0+\sqrt{v_0^2-2gy_1}}{g}$$ biçimindedir. Bu iki çözümden birisi topun yükselirken diğeri de geri düşerken $y_1$ konumuna ulaştığı zamanı belirtir. Bu hesaplamayı Python'da yapmak için $\sqrt{x}$ işlemine ihtiyacımız olacak.

Math Modülü

Python'da özel amaçlı fonksiyonlar, adına modül denilen dosyalarda saklanır ve bu fonksiyonları kullanmak için ilgili modülü kullanacağımızı programımızın içinde belirtmemiz gerekir. Python'da $\sqrt{x}$, $\sin(x)$, $\cos(x)$, $\log(x)$ gibi matematiksel hesaplamalar math modülü içinde tanımlıdır. $\sqrt{x}$ işlemi örneğin math modülü içinde tanımlı olan sqrt() fonksiyonu yardımıyla yapılır. Bir modül içindeki bir fonksiyonu kullanmadan önce programımızda from modul import fonksiyon komutunu girmemiz gerekiyor, bu işleme modülden ilgili fonksiyonu ithal etme (import etme) denir. Dolayısıyla yukarıdaki hesaplamayı aşağıdaki program ile yapabiliriz.


from math import sqrt

v0 = 5
g = 9.81
y1 = 0.2

t1 = (v0 - sqrt(v0**2 - 2*g*y1))/g
t2 = (v0 + sqrt(v0**2 - 2*g*y1))/g

print t1, t2

Bu programın çıktısı şu şekilde olacaktır.


Terminal > python hesap12.py
0.0417063724983 0.977661619347

Burada print ifadesinden sonra iki veriyi virgülle ayırarak yazdık, bu şekilde virgülle ayrılarak sıralanmış nesneler aynı satırda yazdırılır. Ayrıca programın okunaklı olması açısından genellikle import ifadeleri programın ilk satırlarında yazılır ve gerektiğinde boş satırlar bırakılır. Programımızda aynı modülden birden fazla fonksiyon kullanılacaksa bunları virgülle ayırarak from math import sqrt, sin, log, exp biçiminde belirtebiliriz. Modüldeki tüm fonksiyonlara ihtiyacımız olacaksa from math import * komutu ile modüldeki tüm fonksiyonları programımızda kullanılabilir hale getirmiş oluruz. Bunun yerine sadece import math komutunu girersek de modülün tüm fonksiyonlarına erişim sağlamış oluruz, fakat bu durumda o fonksiyonları kullanırken modülün ismini ön ek olarak math.sqrt() biçiminde belirtmemiz gerekir.


import math

v0 = 5
g = 9.81
y1 = 0.2

t1 = (v0 - math.sqrt(v0**2 - 2*g*y1))/g
t2 = (v0 + math.sqrt(v0**2 - 2*g*y1))/g

print t1, t2

Burada kullandığımız ön eki istersek değiştirebiliriz. import math as m komutuyla fonksiyonları m.sqrt() gibi kullanabiliriz.


import math as m

v0 = 5
g = 9.81
y1 = 0.2

t1 = (v0 - m.sqrt(v0**2 - 2*g*y1))/g
t2 = (v0 + m.sqrt(v0**2 - 2*g*y1))/g

print t1, t2

math modülü içinde yukarıda bahsettiğimiz gibi matematiksel fonksiyonların yanında $\pi$ ve $\text{e}$ gibi bazı matematiksel sabitler de vardır.


from math import sin, cos, log, pi
x = 3*pi/2
s = sin(x-1)*cos(x+1) + log(2*x)
print s

Yukarıdaki program aşağıdaki çıktıyı üretecektir.


Terminal > python hesap15.py
1.7886934611

Kompleks Sayılar

İkinci dereceden cebirsel denklemlerin kompleks kökleri var olabilir, bu durumla hesaplamalarda sıklıkla karşılaşırız ve dolayısıyla programlarımızda kompleks sayılarla işlem yapmaya ihtiyacımız olabilir. Şimdi biraz da Python'da kompleks sayı işlemlerine değinelim. Bir kompleks sayı, $a$ ve $b$ reel sayılar olmak üzere $a + i\cdot b$ biçiminde ifade edilir. Buradaki $i$ sayısına sanal birim denir ve $i^2=-1$ yani $i=\sqrt{-1}$ eşitliği ile tanımlanır. Bu sayılar yardımıyla diskrıminantı negatif olan $x^2+2=0$ gibi denklemlerin çözümleri $x_{1,2}=\pm\sqrt{2}i$ biçiminde ifade edilebilir. Python'da sanal birim j sembolü ile gösterilir, örneğin $1+2i$ kompleks sayısı 1 + 2j biçiminde kodlanır. 2j kısmını kodlarken arada * çarpma işareti kullanmadığımıza dikkat edin, ayrıca Python'da pür sanal $i$ sayısını da 1j olarak kodlarız. j sembolünün önünde mutlaka bir sayı gelmeli ve arada çarpma işareti bulunmamalıdır. Bu şekilde tanımlanmış değişkenler Python'da bir complex nesnesi olarak adlandırılır, Pythonda herhangi bir x nesnesinin hangi türden olduğunu anlamak için type(x) komutunu kullanırız. Bunları bir Python oturumunda gözlemleyelim.


>>> x = 3-2j
>>> type(x)

>>> y = 2-1j
>>> type(y)
type 'complex'>

Kompleks sayı nesneleriyle işlem yaparken Python bunların kompleks sayı olduğunu algılar ve otomatik olarak kompleks sayı aritmetiğini kullanır. Şimdi yukarıda tanımladığımız sayılarla bazı işlemler yapalım.


>>> x + y
(5-3j)
>>> 2*y
(4-2j)
>>> y + 2j
(2+1j)

Python'da kompleks sayıların girdiği işlemlerin sonucu her zaman bir complex nesnesi olarak döndürülür. Ancak bir $x$ kompleks sayısının reel ve imajiner kısımları sırasıyla x.real ve x.imag komutlarıyla (Bir nesne üzerinde böyle çalıştırılan komutlara birer metod denir.) birer reel sayı (float) olarak elde edilebilir.


>>> x.real
3.0
>>> x.imag
-2.0

Bunların dışında sonucun her zaman bir complex nesnesi olması bazı zorluklar yaratır. Örneğin bir kompleks sayı hesabının sonucunda imajiner kısım sıfır çıksa bile o sayı float nesnesi yerine hala bir complex nesnesi olarak döner.


>>> z = x - 2*y
>>> z
(-1+0j)
>>> type(z)
type 'complex'>

Hatta manuel olarak bile bu sayıyı bir float nesnesine dönüştüremeyiz. Bunu denersek Python yazılımı bize complex nesnelerinin float nesnelerine dönüştürülemeyeceğini anlatan bir hata mesajı gösterir.


>>> a = float(z)
Traceback (most recent call last):
File "", line 1, in 
TypeError: can't convert complex to float

Böyle bir sayıyı aşağıdaki gibi bir float veya int nesnesine dönüştürmek mümkündür.


>>> a = z.real
>>> a
-1.0
>>> type(a)
type 'float'>

Kompleks Fonksiyonlar

Python'da kompleks sayıları daha önce math modülünde gördüğümüz matematiksel fonksiyonlar içinde kullanamayız, o fonksiyonlar float nesneleriyle çalışacak şekilde tanımlanmışlardır. Mesela yukarıda tanımladığımız x kompleks sayısının sinüs değerini hesaplatmaya çalışırsak aşağıdaki gibi bir hata mesajı ile karşılaşırız.


>>>import math
>>> math.sin(x)
Traceback (most recent call last):
File "", line 1, in 
TypeError: can't convert complex to float

Kompleks değişkenler içeren matematiksel fonksiyonlar Python'un cmath (complex math) modülü içinde tanımlanmıştır ve kompleks matematiksel işlemler için bu modülü kullanmalıyız.


>>> import cmath
>>> cmath.sin(x)
(0.5309210862485197+3.5905645899857794j)

Fakat cmath modülündeki fonksiyonlarla işlem yaparken de sonuçta imajiner kısım sıfır çıkınca bu bir complex nesnesi olarak döner. Bir hesaplama sonucunda imajiner kısım varsa bunun bir complex, yoksa da bunun bir float nesnesi olarak dönmesini arzularız. Bunun için cmath yerine scipy (SciPy, Scientific Python) paketini kullanmalıyız. Burada da tüm matematiksel fonksiyonlar vardır ve hepsi sonuçta imajiner kısım varsa complex, yoksa float nesnesi döndürecek şekilde tanımlanmıştır.


>>> from scipy import sin, pi
>>> x = 3 - 2j
>>> sin(x)
(0.53092108624851975+3.5905645899857799j)
>>> sin(pi)
1.2246467991473532e-16

Yuvarlama Hataları

Bölümü bitirmeden önce biraz da yuvarlama hatalarından bahsetmek gerekiyor, aşağıdaki gözlemi yapalım.


>>> a = 1.0/49
>>> b = 49
>>> a*b
0.9999999999999999

Buradaki hata programlama hatası değildir, bilgisayarların çalışma prensipleri ile ilgili temel bir durumdur bu ve tüm programlama dillerinde böyle durumlarla karşılaşılır. Bir reel sayı aslında çok sayıda basamaktan oluşur (rasyonel değilse sonsuz) ve bilgisayar hafızaları sınırlı olduğundan sadece baştan bir kaç basamağı kullanılarak hafızada tutulurlar. Genellikle bilgisayarlarda 17 basamak kullanılır, dolayısıyla reel sayılarla (float tipi veri) hesaplama yaparken aslında bir miktar hata payı ile çalışıyor oluyoruz, bu tür hatalara yuvarlama hatası denir. print ifadesi ile bir float verisini yazdırırken kaç basamak gösterilmesi gerektiğini belirtmezsek, python az sayıda basamak kullanarak yazdırır ve yuvarlama hatalarını çoğu zaman farketmeyiz. Pythonda reel sayıları istenilen hata payı ile hesaplayabilen ve dolayısıyla sonuçta arzu edilen hata sınırları içinde kalmamızı sağlayan decimal modulü, ve SciPy paketi içinde bulunan mpmath modülü vardır. Fakat bunlara genelde fazla ihtiyaç duymayız çünkü nümerik yöntemlerin geliştirilmesinde yapılan hatalar yuvarlama hatalarından genellikle çok daha büyüktür.

Dersin Ana Sayfası:
Python ve Bilimsel Hesaplama
Sonraki Ders Notu:
2.1. While Döngüleri