C# konsolunda Console.WriteLine(0.1 + 0.2); yazdığınızda ekranda kısaltılmış hâliyle 0.3 görünse de, 0.1 + 0.2 == 0.3 karşılaştırması false döner — çünkü değişkenin içinde saklanan gerçek değer, görüntülenenden ufacık bir miktar farklıdır. Bu belirli bir dile özgü bir hata değil — IEEE 754 standardının kesirli sayıları ikili olarak nasıl temsil ettiğinin doğrudan bir sonucudur ve JavaScript, Java, Python gibi bu standardı kullanan hemen hemen her dilde aynı sorunla karşılaşılır.
Kayan noktalı bir sayının üç parçası
IEEE 754'e göre bir sayı üç bileşen olarak saklanır: bir işaret (pozitif veya negatif), bir mantis (sayının anlamlı basamakları) ve bir üs (virgülün kaydırıldığı kuvvet). Bu, bilimsel gösterime benzer: 1.5 × 10², sadece ikili sistemde.
0.1 neden ikili sistemde tam olarak temsil edilemez
Ondalık sistemde 0.1, ikili sistemde sonsuz bir kesirdir (ondalık sistemde 1/3'ün sonsuz olmasına benzer şekilde). Bir bilgisayar yalnızca sınırlı sayıda mantis biti saklar, bu yüzden sayı en yakın temsil edilebilir değere yuvarlanır — ve görünen "hatayı" tam olarak bu yuvarlama üretir.
Bunun gerçekten zarar verdiği yer: fatura ve alışveriş sepeti toplamları
Ürün fiyatlarını sıradan float olarak toplayan bir ödeme sayfası, yeterince ürün eklendiğinde beklenen toplamdan birkaç kuruş sapabilir — her toplama işlemi hafifçe yuvarlanır ve hatalar birbirini götürmek yerine birikir. Ödeme sistemlerinin genellikle kuruşu tam sayı olarak işlemesinin veya ham float toplamak yerine özel bir decimal türü kullanmasının nedeni budur.
Bu neden gereklidir
- Finansal veya bilimsel hesaplamalarda beklenmedik yuvarlama hatalarını anlamak ve teşhis etmek.
- Belirli bir kayan noktalı sayının tam ikili gösterimini görmek.
- Bir meslektaşa veya öğrenciye kesirli sayıları tam eşitlik için karşılaştırmanın neden kötü bir uygulama olduğunu açıklamak.
Sıfıra yakın subnormal sayılar
Bir sayının değeri, normal gösterim (örtük bir 1 ile başlayan bir anlamlı basamak) için çok küçük olduğunda, IEEE 754 subnormal (denormalize) moda geçer ve bu örtük 1 atılır — bu, sıfıra ani bir sıçrama yerine kademeli bir hassasiyet kaybı pahasına, mutlak değer olarak daha da küçük sayıların temsil edilmesine izin verir. Sıfıra bu "yumuşak" geçiş ani sıfırlanmadan daha iyidir, ama bazı işlemcilerde subnormal hesaplamalar normal hesaplamalardan belirgin şekilde daha yavaştır.