정확한 답이 필요한 계산에는 float나 double을 피하라
소수점 추적은 시스템에 맡기고, 코딩 시의 불편함이나 성능저하를 신경 쓰지 않겠다면
BigDecimal을 사용하라. BigDecimal이 제공하는 여덟 가지 반올림 모드를 이용하여 반올림을 완벽하게 제어할 수 있다. 법으로 정해진 반올림을 수행해야 하는 비즈니스 계산에서 아주 편리한 기능임
반면, 성능이 중요하고 소수점을 직접 추적할 수 있고 숫자가 너무 크지 않다면 int나 long을 사용하라
숫자를 아홉 자리 십진수로 표현 가능하면 int를, 열여덟자리 십진수로 표현할 수 있다면 long을. 열여덟 자리를 넘어가면 BigDecimal을 사용해야 한다.
개요
- float와 double 타입은 과학과 공학 계산용으로 설계되었다. 이진 부동소수점 연산에 쓰이며, 넓은 범위의 수를 빠르게 정밀한 ‘근사치’로 계산하도록 세심하게 설계되었다.
package effectivejava.chapter9.item60; public class Change { // Broken - uses floating point for monetary calculation! public static void main(String[] args) { double funds = 1.00; int itemsBought = 0; for (double price = 0.10; funds >= price; price += 0.10) { funds -= price; itemsBought++; } System.out.println(itemsBought + " items bought."); System.out.println("Change: $" + funds); } }
금융 계산에는 BigDecimal, int 혹은 long을 사용해야 함
BigDecimal
package effectivejava.chapter9.item60; import java.math.BigDecimal; public class BigDecimalChange { public static void main(String[] args) { final BigDecimal TEN_CENTS = new BigDecimal(".10"); int itemsBought = 0; BigDecimal funds = new BigDecimal("1.00"); for (BigDecimal price = TEN_CENTS; funds.compareTo(price) >= 0; price = price.add(TEN_CENTS)) { funds = funds.subtract(price); itemsBought++; } System.out.println(itemsBought + " items bought."); System.out.println("Money left over: $" + funds); } }
BigDecimal
초기화 시,String
으로 초기화 한것 주목. 계산 시 부정확한 값이 사용되는 걸 막기 위해 필요한 조치
- 그러나 단점은 기본타입보다 쓰기가 훨씬 불편하고 훨씬 느림.
int, long
- 다룰 수 있는 값의 크기가 제한되고, 소수점을 직접 관리해야 함
- 위 예시에서는 모든 계산을 달러 대신 센트로 수행하면 문제가 해결됨
package effectivejava.chapter9.item60; public class IntChange { public static void main(String[] args) { int itemsBought = 0; int funds = 100; for (int price = 10; funds >= price; price += 10) { funds -= price; itemsBought++; } System.out.println(itemsBought + " items bought."); System.out.println("Cash left over: " + funds + " cents"); } }