1

Kayan nokta aritmetiğinde √2 · √2 neden tam 2 olmayabilir?

Aşağıdaki Python kodunda sqrt(2) değeri IEEE 754 binary64 (Python float) olarak saklanır:

import math

x = math.sqrt(2)
y = x * x - 2.0

print(f"x = {x:.17g}")
print(f"x*x - 2 = {y:.17g}")
print(math.isclose(x * x, 2.0, rel_tol=1e-15))

Tipik CPython çıktısı şöyledir:

x = 1.4142135623730951
x*x - 2 = 4.4408920985006262e-16
True

Matematiksel olarak $\left(\sqrt{2}\right)^2-2=0$ olduğu hâlde kayan nokta hesabında neden küçük bir artık kalır? Sonucun neden doğrudan == 0 ile karşılaştırılmaması gerektiğini ve math.isclose kullanımını açıklayın.

Gönderiye eklenen görselGönderiye eklenen görselGönderiye eklenen görsel
Bu içerik Moderatör tarafından düzenlendi. (21.07.2026 00:51)

2 Cevap

1
Kabul Edilen Cevap

Temel neden temsil hatasıdır. $\sqrt{2}$ irrasyonel olduğu için sonlu sayıda ikilik basamakla tam gösterilemez. math.sqrt(2), gerçek değere en yakın binary64 sayılarından birini üretir. Bu yaklaşım yeniden karesini aldığımızda yuvarlama bir kez daha devreye girer.

import math

x = math.sqrt(2)
squared = x * x

print(f"{x:.17g}")
print(f"{squared:.17g}")
print(f"artık = {squared - 2.0:.17g}")
print(f"2 çevresindeki ULP = {math.ulp(2.0):.17g}")
1.4142135623730951
2.0000000000000004
artık = 4.4408920985006262e-16
2 çevresindeki ULP = 4.4408920985006262e-16

Buradaki artık, $2$ çevresinde temsil edilebilen komşu iki float arasındaki uzaklıkla aynı mertebededir. Bu bir matematik hatası değil, sonlu duyarlıklı sayı temsilinin beklenen sonucudur.

Bu nedenle kayan noktalı değerler toleransla karşılaştırılır:

math.isclose(x * x, 2.0, rel_tol=1e-15, abs_tol=0.0)

Decimal duyarlılığı artırabilir fakat irrasyonel $\sqrt{2}$ değerini sonlu basamakta yine tam temsil etmez. Sembolik olarak tam sonuç gerekiyorsa sembolik cebir; sayısal hesapta ise probleme uygun hata toleransı kullanılmalıdır.

0

Ek bir ayrım önemlidir: math.ulp(1.0) yaklaşık $2.22\times10^{-16}$ iken, $2$ çevresindeki aralık math.ulp(2.0) ile yaklaşık $4.44\times10^{-16}$ olur. Bu örnekte görülen artık ikincisidir.

import math

print(math.ulp(1.0))
print(math.ulp(2.0))
print(math.sqrt(2).hex())

float.hex() değerin bellekteki ikilik yaklaşıma karşılık gelen kesin onaltılık gösterimini verir. Böylece problemin Python sözdiziminden değil, kullanılan binary64 temsilinden kaynaklandığı doğrudan görülebilir.

Bu içerik Moderatör tarafından düzenlendi. (21.07.2026 00:51)
Çözüme katkı ver

Cevabını açık ve gerekçeli yaz.

Cevap yazmak için giriş yapmalısınız.