Skip to content

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

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을 사용하라.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions