JavaScript ile yuvarlarma hesap hatası nasıl düzeltilir?

JavaScript Hesap hataları özellikle yuvarlatma(round) anında çok karşımıza çıkıyor. Özellikle küsuratlı hesaplarda bu hataları nasıl düzelteceğimizi ve doğru sonucu hangi yoldan elde edeceğimizi göreceğiz. Birçok JavaScript dökümanı inceledim ama bu konuda net bir açıklama görmedim.

JavaScript Math Kütüphanesi ve Round Fonksiyonu

İlk önce round fonksiyonunun nasıl kullanıldığını anlayalım.


// İşlemin sonucu 19 döner.
x = Math.round(19.49);
 
// İşlemin sonucunda 20 döner
x = Math.round(19.5);
 
// Sonuçta -19 döner.
x = Math.round(-19.5);
 
// Sonuçta -20 döner.
x = Math.round(-19.51);
 




Aşağıdaki işlemin sonucu yanlış olarak 1 dönecektir. Bu  işlemin sonucunu Math.round10(1.005, -2)  ile karşılaştırıp bir bakın. 

x = Math.round(1.005*100)/100;

Yuvarlatma Hataları

Yuvarlatma hatalarının iki şekilde yapıldığını çok görüyoruz, birincisi Number.prototype.toFixed() şeklinde yapılan yuvarlatma, ikincisi ise sayıyı 100 ile çarpıp, 100'e böldüğümüzde karşılaştığımız hata.  

Şimdi  aşağıdaki işlemi örnek alalım.

Number((1.005).toFixed(2)); 
Bu işlemin sonucunda 1.01 yerine 1.0 dönecektir, sonuç yanlıştır.

Aşağıdaki işlemde de 1.005 sayısı, virgülden sonra 2 haneye düşürülmek istenmiştir.

Math.round(1.005*100)/100;
Bu işlemin sonucunda da 1.01 yerine 1.0 dönecektir, sonuç yanlıştır.

JavaScript Yuvarlatma Hatasını Önlemek

Yuvarlatma hatasını gidermek için Eksponensiyel(üstel) yazım şeklini kullanabiliriz. Aşağıdaki işlemin sonucunda tam da istediğimiz gibi iki haneye sayı yuvarlatılacak ve sonuç 1.01 olacaktır.

Number(Math.round(1.005+'e2')+'e-2');
Yukarıdaki kullanımdan sürekli yararlanmak için, bir JavaScript fonksiyonu şeklinde yazmak istersek;

function yuvarla(sayi, hane{
    return Number(Math.round(sayi+'e'+hane)+'e-'+hane);
}

Bu fonksiyonu aşağıdaki şekilde çağırıp, kullanabiliriz.
yuvarla(1.005, 2);  // Sonuç 1.01 olacaktır.

Bu problemle karşılaşmış olanlar, küsüratlar çok küçük olduğundan belki zamanında çok önemsememiş olabilirler. Ama bir fatura altında toplam aldığınızı, KDV, İskonto vs. hesabını JavaScript ile yaptığınızı düşünün. Hesap hatası sonucu, fatura toplamında yanlışlıklar çıkacaktır, bir de binlerce fatura olduğundan sıkıntı katlanacaktır. Küçük ama önemli bir bilgi... Yeni yazılarda görüşmek üzere, sağlıcakla kalın... 
 

KAYNAKLAR
http://www.jacklmoore.com/notes/rounding-in-javascript/ Bookmark and Share
Dil Değiştir(Change Language)