koddla

Yazılımcıları bilgi ile güçlendirir.

Math modülü

Bu modül, C standardı tarafından tanımlanan matematiksel fonksiyonlara erişim sağlar.

Bu fonksiyonlar karmaşık sayılarla kullanılamaz; karmaşık sayılar için destek istediğimizde cmath modülünden aynı isimdeki işlevleri kullanabiliriz. Karmaşık sayıları destekleyen ve desteklemeyen fonksiyon ayrımı çoğu kullanıcının bu kadar fazla matematik ile uğraşmamak istemesi.

Math modülü ile yuvarlama: round, floor, ceil ve trunc

Pythonda yerleşik olarak gelen round fonksiyonuna ilaveten, math modülü floorceil, ve trunc fonksiyonlarını içerir.

x = 1.55
y = -1.55

# en yakın tam sayıya yuvarla
round(x)       #  2
round(y)       # -2

# ikinci argüman ne kadar ondalıklı sayı kullanılacağını söyler (varsayılan 0)
round(x, 1)    #  1.6
round(y, 1)    # -1.6

# math modülü bir modül olduğuna göre önce import edilmesi gerekir.
# ardından kullanılabilir.
import math

# x'ten küçük en büyük tam sayı
math.floor(x)  #  1
math.floor(y)  # -2

# x'ten büyük en küçük tam sayı
math.ceil(x)   #  2
math.ceil(y)   # -1

# x'in ondalık kısmını kaybet
math.trunc(x)  #  1, pozitif sayılar için math.floor ile eşdeğer
math.trunc(y)  # -1, negatiff sayılar için math.ceil ile eşdeğer

floorceiltrunc, ve round her zaman float döndürür.

round(1.3)  # 1.0

Uyarı! 

Tüm float gösterimlerinde olduğu gibi, bazı sayılar tam olarak gösterilemeyebilir. Bu durum beklenmeyen yuvarlama hatalarına neden olur.

round(2.675, 2)  # 2.67, 2.68 değil!

Uyarı: floor, trunc, ve negatif sayılarrın integer bölümü

Python (ve C++ ve Java) negatif sayılar için sıfırdan uzaklaşmayı tercih ederler:

>>> math.floor(-1.7)
-2.0
>>> -5 // 2
-3

Math modülü ile kök alma: math.sqrt ve cmath.sqrt

math modülü kök almaya yarayan math.sqrt()-fonksiyonunu içerir. Döndürülen sonuç her zaman float olur::

import math

math.sqrt(9)                # 3.0
math.sqrt(11.11)            # 3.3331666624997918
math.sqrt(Decimal('6.25'))  # 2.5

Eğer sonuç bir kompleks sayı ise math.sqrt() fonksiyonu bir ValueError hatası verir:

math.sqrt(-10)

ValueError: math domain error

math.sqrt(x) işlevi math.pow(x, 0.5) veya x ** 0.5 ifadelerinden daha hızlıdır. Ancak bu ifadelerin sonuçları aynı doğruluktadır. math modülüne benzer olan cmath modülü ise kompleks sayılar için de kök alabilir. Sonuçlar a + bi şeklindedir.

import cmath

cmath.sqrt(4)  # 2+0j
cmath.sqrt(-4) # 2j

Peki bu j ne oluyor? j kök -1 ifadesine eşdeğerdir. Tüm sayılar a + bi formunda yazılabilir, ya da bu örnekte a + bj şeklinde. a, bu ifadede sayının gerçek kısmını verir; 2+0j örneğinde 2. Bu sayının imajiner kısmı olmadığı için b 0’a eşit olur. b imajiner kısmı gösterir; 2j ifadesindeki 2 gibi. 2j ifadesinde reel kısım olmadığı için 0 + 2j şeklinde de yazılabilir.

Math modülü ile trigonometri

Hipotenüs hesaplama

math.hypot(2, 4) # SquareRoot(2**2 + 4**2) ifadesinin kısa hali
# Çıktı: 4.47213595499958

Dereceden radyana, radyandan dereceye dönüştürme

Tüm math fonksiyonları argüman olarak radyan bekler. Dolayısıyla öncelikle dereceden radyana dönüştürülmeleri gerekir:

math.radians(45)              # 45 dereceyi radyana dönüştür
# Çıktı: 0.7853981633974483

Tüm ters-trigonometrik fonksiyonlar radyan sonuç verirler. Dolayısıyla dereceye geri döndürülmeleri gerekebilir.

math.degrees(math.asin(1))    # asin sonucunu dereceye döndür
# Çıktı: 90.0

Sine, cosine, tangent ve ters fonksiyonlar 

# Sin ve arc sin
math.sin(math.pi / 2)
# Çıktı: 1.0
math.sin(math.radians(90))   # Sin(90derece)
# Çıktı: 1.0

math.asin(1)
# Çıktı: 1.5707963267948966    # "= pi / 2"
math.asin(1) / math.pi
# Çıktı: 0.5

# Cos ve arc cos:
math.cos(math.pi / 2)
# Çıktı: 6.123233995736766e-17 
# Neredeyse 0'a eşit ama tam eşit değil çünkü "pi" kısıtlı bir kesinlikteki float !

math.acos(1)
# Çıktı: 0.0

# Tan and arc tan:
math.tan(math.pi/2)
# Çıktı: 1.633123935319537e+16 
# Çok büyük ama tam olarak sonsuz değil çünkü "pi" kısıtlı bir kesinlikteki float !
#  Python 3
math.atan(math.inf)
# Çıktı: 1.5707963267948966 # "pi / 2"
math.atan(float('inf'))
# Çıktı: 1.5707963267948966 # "pi / 2"

math.atan haricinde iki-argüman alan math.atan2 fonksiyonu da bulunur. Bu fonksiyon doğru kuadrantın hesaplanmasını ve sıfıra bölmeden kaynaklanan hataları engeller.

math.atan2(1, 2)   # "math.atan(1/2)"'ye eş değer
# Çıktı: 0.4636476090008061 # ≈ 26.57 derece, ilk kuadrant

math.atan2(-1, -2) # "math.atan(-1/-2)" == "math.atan(1/2)" eşit değil
# Çıktı: -2.677945044588987 # ≈ -153.43 derece (veya 206.57 derece), 3. kuadrant

math.atan2(1, 0)   # math.atan(1/0) ZeroDivisionError hatası verir
# Çıktı: 1.5707963267948966 # "pi / 2"

Hiperbolik sin, cos ve tan 

# Hiperbolik sin 
math.sinh(math.pi) # = 11.548739357257746
math.asinh(1)      # = 0.8813735870195429

# Hiperbolik cos 
math.cosh(math.pi) # = 11.591953275521519
math.acosh(1)      # = 0.0

# Hiperbolik tan
math.tanh(math.pi) # = 0.99627207622075
math.atanh(0.5)    # = 0.5493061443340549

Math modülü ile logaritma

math.log(x) x’in doğal logaritmadaki (e tabanında) değerini verir

math.log(math.e)  # 1.0
math.log(1)       # 0.0
math.log(100)     # 4.605170185988092

math.log 1’e yakın sayılarda kesinliğini kaybeder. Bu durum float sayılardaki kısıtlama nedeniyledir. 1’e yakın sayıların logaritmasını daha hassas elde etmek için math.log1p kullanılır. Bu fonksiyon 1+argüman ifadesinin logaritmasını alır:

math.log(1 + 1e-20)  # 0.0
math.log1p(1e-20)    # 1e-20

math.log10 10 tabanındaki logaritma için kullanılır:

math.log10(10)  # 1.0

İki argüman verildiğinde, ikinci argüman tabanı belirtir. math.log(x, taban):

math.log(100, 10) # 2.0
math.log(27, 3)   # 3.0
math.log(1, 10)   # 0.0

Math modülünde matematik sabitleri

math modülü yaygın olarak kullanılan iki matematik sabitini içerir

  • math.pi – pi sayısı
  • math.e – e sayısı (doğal logaritmdeki e tabanı)
>>> from math import pi, e
>>> pi
3.141592653589793
>>> e
2.718281828459045
>>>

Python 3.5’ten itibaren sonsuzluk için ve sayı olmayan değerler için de inf ve nan (“not a number”) sabitleri bulunur. Önceki versiyonlardaki float’a string argümanının verildiği syntax hala geçerlidir.

math.inf == float('inf')
# Çıktı: True

-math.inf == float('-inf')
# Çıktı: True

# NaN hiçbir zaman bir şeye eşit olmaz, kendisine bile 
math.nan == float('nan')
# Çıktı: False

Infinity ve NaN (not a number)

Python’un tüm versiyonlarında sonsuz ve NaN (“not a number”) ifadelerini aşağıdaki gibi gösterebiliriz:

pos_inf = float('inf')     # pozitif sonsuz
neg_inf = float('-inf')    # negatif fsonsuz
not_a_num = float('nan')   # NaN ("not a number")

Python 3.5 ve sonrasında ayrıca math.inf ve math.nan sabitlerini de kullanabiliriz:

pos_inf = math.inf
neg_inf = -math.inf
not_a_num = math.nan

String çıktısı olalrak ise aşağıdaki sonucu alırız

pos_inf, neg_inf, not_a_num
# Çıktı: (inf, -inf, nan)

Pozitif veya negatif sonsuz ifadesini isinf methodu ile test ederiz:

math.isinf(pos_inf)
# Çıktı: True

math.isinf(neg_inf)
# Çıktı: True

Direkt mukayese ile de pozitif ve negatifi test ederiz:

pos_inf == float('inf')    # or  == math.inf Python 3.5+
# Çıktı: True

neg_inf == float('-inf')   # or  == -math.inf Python 3.5+
# Çıktı: True

neg_inf == pos_inf
# Çıktı: False

Python 3.2 ve sonrasında sonlu ifadeleri isfinite ile kontrol edebiliriz:

math.isfinite(pos_inf)
# Çıktı: False

math.isfinite(0.0)
# Çıktı: True

Karşılaştırma ifadeleri pozitif ve negatif sonsuz için beklenildiği gibi sonuç verir:

import sys

sys.float_info.max
# Çıktı: 1.7976931348623157e+308  (sonuç sisteme bağlıdır)

pos_inf > sys.float_info.max
# Çıktı: True

neg_inf < -sys.float_info.max
# Çıktı: True

Artimetik bir ifade float ile gösterebileceğimiz değerden daha büyük bir değer döndürürse, sonuç yine sonsuz olur.

pos_inf == sys.float_info.max * 1.0000001
# Çıktı: True

neg_inf == -sys.float_info.max * 1.0000001
# Çıktı: True

Ancak sıfıra bölme sonsuz sonucunu vermez. ZeroDivisionError hatası üretirr.

try:
    x = 1.0 / 0.0
    print(x)
except ZeroDivisionError:
    print("Sıfıra bölme")

# Çıktı: Sıfıra bölme

Sonsuz üzerindeki aritmetik işlemler sonsuz sonucunu verir, bazen de NaN:

-5.0 * pos_inf == neg_inf
# Çıktı: True

-5.0 * neg_inf == pos_inf
# Çıktı: True

pos_inf * neg_inf == neg_inf
# Çıktı: True

0.0 * pos_inf
# Çıktı: nan

0.0 * neg_inf
# Çıktı: nan

pos_inf / pos_inf
# Çıktı: nan

NaN hiç bir zaman bir şeye eşit olmaz. Kendisine bile. NaN’ı isnan ile test ederiz:

not_a_num == not_a_num
# Çıktı: False

math.isnan(not_a_num)
Çıktı: True

NaN her zaman “eşit değil” ile kıyas edilir. Büyüktür ve küçüktür ifadeleri ile test edilmez:

not_a_num != 5.0   # ya da herhangi bir sayı
# Çıktı: True

not_a_num > 5.0   veya  not_a_num < 5.0   veya   not_a_num == 5.0
# Çıktı: False

NaN üzerindeki aritmetik işlemler her zaman NaN verir. -1 ile çarpma işlemi de buna dahildir: “negatitf NaN” değeri bulunmaz.

5.0 * not_a_num
# Çıktı: nan

float('-nan')
# Çıktı: nan
-math.nan
# Çıktı: nan

Eski float yönteminde gösterilen NaN ve sonsuz ile Python 3.5+’deki math kütüphanesi sabitleri arasında belirgin bir fark bulunmaz:

math.inf is math.inf, math.nan is math.nan
# Çıktı: (True, True)

float('inf') is float('inf'), float('nan') is float('nan')

Daha hızlı üs almak için Pow

timeit modülü ile üs almayı kontrol edelim:

> python -m timeit 'for x in xrange(50000): b = x**3'
10 loops, best of 3: 51.2 msec per loop
> python -m timeit 'from math import pow' 'for x in xrange(50000): b = pow(x,3)' 
100 loops, best of 3: 9.15 msec per loop

Yerleşik ** operatorü çoğunlukla daha kolay kullanılır ancak performans söz konusu olduğunda math.pow daha değerlidir. Bununla birlikte pow’un float döndürdüğünü unutmamak gerekir; argüman bir tam sayı olsa bile:

> from math import pow
> pow(5,5)
3125.0

İşaretlerin kopyalanması

Python 2.6 ve sonrasında, math.copysign(x, y) metodu x‘i y‘nin işareti ile verir. Döndürülen değer her zaman float olur.

math.copysign(-2, 3)    # 2.0
math.copysign(3, -3)    # -3.0
math.copysign(4, 14.2)  # 4.0
math.copysign(1, -0.0)  # -1.0, işaretli sıfır değerini destekleyen sistemlerde

İmajiner sayılar

Imajiner sayılar Python’da “j” veya “J” ile gösterilir

1j         # kök -1'e eşdeğer.
1j * 1j    # = (-1+0j)

Kompleks sayılar ve cmath modülü

cmath modülü math modülüne benzerdir. Ancak kompleks sayılar için tanımlanmış fonksiyonlar barındırır.

Öncelikle, kompleks sayılar Python dilinde tanımlı nümerik ifadelerdir, harici bir kütüphane ile gelmez. Dolayısıyla sıradan aritmetik işlemler için cmath’i import etmemiz gerekmez.

Unutmayın: j (veya J) kullanıyoruz, i değil.

z = 2 + 1j

1j ifadesini kullanırız. Çünkü j nümerik bir gösterimden ziyade başka bir değişken ismi de olabilir.

1j * 1j
Çıktı: (-1+0j)

1j ** 1j
# Çıktı: (0.20787957635076193+0j)     # "i üzeri i"  ==  math.e ** -(math.pi/2)

real kısım ve imag (imajiner) kısma ilaveten kompleks konjüge değeri de bulunur:

# real ve imajiner kısımlar float 
z.real, z.imag
# Çıktı: (1.0, 3.0)

z.conjugate()
# Çıktı: (1-3j)    # z.conjugate() == z.real - z.imag * 1j

abs ve complex yerleşik fonksiyonları da aynı şekilde dilin bir parçasıdır. Dolayısıyla herhangi bir import gerektirmezler:

abs(1 + 1j)
# Çıktı: 1.4142135623730951     # kök 2

complex(1)
# Çıktı: (1+0j)

complex(imag=1)
# Çıktı: (1j)

complex(1, 1)
# Çıktı: (1+1j)

complex fonksiyonu argüman olarak bir string alabilir, ancak string boşluk içeremez:

complex('1+1j')
# Çıktı: (1+1j)

complex('1 + 1j')
# Exception: ValueError: complex() arg is a malformed string

Ancak çoğu fonksiyon için modülü import etmemiz gerekir, örneğin sqrt:

import cmath

cmath.sqrt(-1)
# Çıktı: 1j

Doğal olarak sqrt metodunun davranışı kompleks ve reel sayılar için farklı olacaktır. Kompleks fonksiyonları içermeyen math için negatif sayıların kökü hata verir:

import math

math.sqrt(-1)
# Exception: ValueError: math domain error

Polar koordinat dönüşümü

cmath.polar(1 + 1j)
# Çıktı: (1.4142135623730951, 0.7853981633974483)    # == (sqrt(1 + 1), atan2(1, 1))

abs(1 + 1j), cmath.phase(1 + 1j)
# Çıktı: (1.4142135623730951, 0.7853981633974483)    # bir önceki ile aynı

cmath.rect(math.sqrt(2), math.atan(1))
# Çıktı: (1.0000000000000002+1.0000000000000002j)

cmath modülü math modülünün direkt karşılığı olan fonksiyonları da içerir.

sqrt metoduna ilaveten, exploglog10, trigonometrik ve ters trigonometrik (sincostanasinacosatan), hiperbolik ve ters hiperbolik (sinhcoshtanhasinhacoshatanh). ifadelerin de kompleks versiyonları bulunur. Ancak math.atan2‘nin kompleks karşılığı yoktur

cmath.log(1+1j)
# Çıktı: (0.34657359027997264+0.7853981633974483j)

cmath.exp(1j * cmath.pi)
# Çıktı: (-1+1.2246467991473532e-16j)   # e üzeri i pi == -1, yuvarlama hatası ile

pi ve e sabitleri de tanımlıdır. Bu sayıların float olduğu ve kompleks olmadığını unutmayın.

type(cmath.pi)
# Çıktı: <class 'float'>

cmath modülü aynı zamanda isinf, ve (Python 3.2+) isfinite ifadelerinin de kompleks formlarını içerir. Bir kompleks sayının reel veya imajiner kısmı sonsuz ise kompleks sayı sonsuz kabul edilir.

cmath.isinf(complex(float('inf'), 0.0))
# Çıktı: True

Benzer şekilde, cmath modülü isnan‘ın da kompleks varyantını içerir. Bir kompleks sayının reel veya imajiner kısmı NaN ise kompleks sayı NaN kabul edilir.

cmath.isnan(0.0, float('nan'))
# Çıktı: True

Ancak, cmath‘de math.inf ve math.nan sabitlerinin karşılığı yoktur (Python 3.5+)

cmath.isinf(complex(0.0, math.inf))
# Çıktı: True

cmath.isnan(complex(math.nan, 0.0))
# Çıktı: True

cmath.inf
# Exception: AttributeError: module 'cmath' has no attribute 'inf'

Python 3.5 ve sonrasında, isclose metodu cmath ve math modülleri için tanımlıdır.

z = cmath.rect(*cmath.polar(1+1j))

z
# Çıktı: (1.0000000000000002+1.0000000000000002j)

cmath.isclose(z, 1+1j)
# True

Bir yanıt yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Back to top