English version is at DZone
İlkokulda çözmeye alıştığımız basit bir problemi bir de Java’da yazacağımız kodla çözmeye çalışalım.
İlkokulda çözmeye alıştığımız basit bir problemi bir de Java’da yazacağımız kodla çözmeye çalışalım.
Klasik problem şöyle:
Ali’nin cebinde 1 TL’si vardır, Ali cebindeki para ile
bakkaldaki, 10 Kr’luk şekerlerden kaç tane alabilir?
Java Kodumuz:
public static void main(String[] args) { float alininParasi = 1.00f; float sekerinFiyati = 0.10f; int aldigiSekerlerinSayisi = 0; System.out.println("Ali'nin cebinde, " + alininParasi + " TL'si vardir."); System.out.println("Bakkaldaki sekerin tanesi " + sekerinFiyati + " TL'dir."); while (alininParasi >= sekerinFiyati) { aldigiSekerlerinSayisi++; alininParasi -= sekerinFiyati; } System.out.println("Hesaplamamiza gore, Ali bakkaldan " + aldigiSekerlerinSayisi + " seker alabilir ve cebinde de " + alininParasi + " TL'si kalir."); }
Ali'nin cebinde, 1.0 TL'si vardir.
Bakkaldaki sekerin tanesi 0.1
TL'dir.
Hesaplamamiza gore, Ali
bakkaldan 9 seker alabilir ve cebinde de 0.09999993 TL'si kalir.
Nasıl olur?
Burada, beklentimizden farklı bir
sonuç görmemizin nedeni, kodumuzda parasal değerleri float(veya abisi double) veri
tiplerinde tutmamızdır. Java’da float ve double veri tipleri, bilimsel ve
mühendislik hesaplamalarında, hızlı ve doğru sonuçlar elde etmek üzere
tasarlanmışlardır. Bu sebepten, tam(exact) sonuçlar beklediğimiz parasal
hesaplamalarda bu veri tiplerini kullanmamamız gerekir. Bunun yerine BigDecimal,
int veya long veri tiplerini kullanmamız gerekir.
public static void main(String[] args) { BigDecimal alininParasi = new BigDecimal("1.00"); BigDecimal sekerinFiyati = new BigDecimal("0.10"); int aldigiSekerlerinSayisi = 0; System.out.println("Ali'nin cebinde, " + alininParasi + " TL'si vardir."); System.out.println("Bakkaldaki sekerin tanesi " + sekerinFiyati + " TL'dir."); while (alininParasi.compareTo(sekerinFiyati) >= 0) { aldigiSekerlerinSayisi++; alininParasi = alininParasi.subtract(sekerinFiyati); } System.out.println("Hesaplamamiza gore, Ali bakkaldan " + aldigiSekerlerinSayisi + " seker alabilir ve cebinde de " + alininParasi + " TL'si kalir."); }
Ali'nin cebinde, 1.0 TL'si vardir.
Bakkaldaki sekerin tanesi 0.1 TL'dir.
Hesaplamamiza gore, Ali bakkaldan 10 seker alabilir ve cebinde de 0.0 TL'si kalir.
Evet şimdi oldu.
Burada BigDecimal kullanımı ile ilgili iki dezavantajdan
bahsedebiliriz:
- Primitive tipler kadar kullanışlı değil
- Yavaş
Basit hesaplamalar için ikincisi pek canımızı sıkmasa da,
ilki bazen sinir bozucu olabilir.
public static void main(String[] args) { int alininParasi = 100; int sekerinFiyati = 10; int aldigiSekerlerinSayisi = 0; System.out.println("Ali'nin cebinde, " + (alininParasi*0.01) + " TL'si vardir."); System.out.println("Bakkaldaki sekerin tanesi " + (sekerinFiyati*0.01) + " TL'dir."); while (alininParasi >= sekerinFiyati) { aldigiSekerlerinSayisi++; alininParasi -= sekerinFiyati; } System.out.println("Hesaplamamiza gore, Ali bakkaldan " + aldigiSekerlerinSayisi + " seker alabilir ve cebinde de " + (alininParasi *0.01) + " TL'si kalir."); }
Ali'nin cebinde, 1.0 TL'si vardir.
Bakkaldaki sekerin tanesi 0.1 TL'dir.
Hesaplamamiza gore, Ali bakkaldan 10 seker alabilir ve cebinde de 0.0 TL'si kalir.
Bakkaldaki sekerin tanesi 0.1 TL'dir.
Hesaplamamiza gore, Ali bakkaldan 10 seker alabilir ve cebinde de 0.0 TL'si kalir.
BigDecimal ve int veri tipleri arasındaki performans farkını, Ali’nin parasını 1.000.000 TL’ye çıkardığımız aşağıdaki program çıktılarında görebiliriz.
Program Çıktısı(BigDecimal):
Ali'nin cebinde, 1000000.0 TL'si
vardir.
Bakkaldaki sekerin tanesi 0.1 TL'dir.
Hesaplamamiza gore, Ali
bakkaldan 10000000 seker alabilir ve cebinde de 0.0 TL'si kalir.
islem suresi: 460 ms
Program Çıktısı(int):
Ali'nin cebinde, 1000000.0 TL'si
vardir.
Bakkaldaki sekerin tanesi 0.1 TL'dir.
Hesaplamamiza gore, Ali
bakkaldan 10000000 seker alabilir ve cebinde de 0.0 TL'si kalir.
islem suresi: 12 ms
Yararlandığım Kaynaklar:
Using double/long vs BigDecimal for monetary calculations
Efective Java 2nd Edition, J. Bloch
Yararlandığım Kaynaklar:
Using double/long vs BigDecimal for monetary calculations
Efective Java 2nd Edition, J. Bloch