정확한 답이 필요하다면 float과 double은 피하라

float, double

float과 double 타입은 과학과 공학 계산용으로 설계되었다. 이진 부동소수점 연산에 쓰이며, 넓은 범위의 수를 빠르게 정밀한 근사치로 계산하도록 세심하게 설계되었다. 따라서 정확한 결과가 필요할 때는 사용하면 안 된다. float과 double 타입은 특히 금융 관련 계산과는 맞지 않다. 0.1 혹은 10의 음의 거듭제곱 수를 표현할 수 없기 때문이다.

System.out.println(1.03 - 0.42);  // 0.6100000000000001

System.out.println(1.00 - 9 * 0.10);  // 0.09999999999999998

금융 계산에 부동소수 타입을 사용한 잘못된 경우

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 + "개 구입");
    System.out.println("잔돈(달러): " + funds);

    // 3개 구입
    // 잔돈(달러): 0.3999999999999999
}

BigDecimal, int 혹은 long

금융 계산에는 BigDecimal, int 혹은 long을 사용해야 한다.

BigDecimal 활용

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 + "개 구입");
    System.out.println("잔돈(달러): " + funds);

    // 4개 구입
    // 잔돈(달러): 0.00
}

BigDecimal을 사용하면 정확한 답을 구할 수 있다. 하지만 BigDecimal은 기본 타입보다 쓰기가 불편하고, 훨씬 느리다.
소수점 추적은 시스템에 맡기고, 코딩 시의 불편함이나 성능 저하를 신경 쓰지 않겠다면 BigDecimal을 사용하자. BigDecimal이 제공하는 여덟 가지 반올림 모드를 이용하여 반올림을 완벽히 제어할 수 있다. 법으로 정해진 반올림을 수행해야 하는 비즈니스 계산에서 아주 편리한 기능이다.

정수타입 활용

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 + "개 구입");
    System.out.println("잔돈(센트): " + funds);

    // 4개 구입
    // 잔돈(달러): 0.00
}

성능이 중요하고 소수점을 직접 추적할 수 있고 숫자가 너무 크지 않다면 int나 long을 사용하자. 숫자를 아홉 자리 십진수로 표현할 수 있다면 int를 사용하고, 열여덟 자리 십진수로 표현할 수 있다면 long을 사용하자. 열여덟 자리를 넘어가면 BigDecimal을 사용해야 한다.

Comments