Skip to content

[아이템 60] 정확한 답이 필요하다면 float와 double은 피하라 #36

@DongLee99

Description

@DongLee99

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

float와 double 타입은 넓은 범위의 수를 빠르게 정밀한 **'근사치'**로 계산하도록 설계되었다. 따라서 정확한 결과가 필요할 때는 사용하면 안 된다.

  • 특히 float와 double은 금융 관련 계산에서는 사용하면 안 된다. (0.1 혹은 10의 음의 거듭 제곱 수를 표현할 수 없기 떄문이다.
System.out.println(1.03 - 0.42);
image

다음과 같이 0.61이 아닌 0.6100000000000001을 출력한다. 잘못된 결과다!

해결방안

float, double이 아닌 BigDecimal, int 혹은 long을 사용하라.

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);
    }
image

다음 코드는 드디어 정상적인 결과가 출력됐다. double이나 float이 아닌 BigDecimal을 사용해 구현을 한 코드이다. 하지만 BigDecimal 에도 단점이 있다.

  • 기본 타입보다 쓰기가 훨씬 불편하고 느리다.

BigDecimal의 대안으로 int나 long 타입을 사용할 수 있다. 하지만 이는 다룰 수 있는 값의 크기가 제한되고, 소수점을 직접 관리해야 한다.

    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);
    }
image

핵심 정리

정확한 답이 필요한 계산에는 float나 double을 피하라. 성능 저하를 신경 쓰지 않겠다면 BigDecimal을 사용하고, 성능이 중요하고 소수점을 직접 추적할 수 있고 숫자가 너무 크지 않다면 int나 long을 사용하라.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions