peaches-book-study / effective-java

이펙티브 자바 3/E
0 stars 2 forks source link

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

Open Lainlnya opened 5 months ago

Lainlnya commented 5 months ago

Chapter : 9. 일반적인 프로그래밍 원칙

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

Assignee : Lainlnya


🍑 서론

float와 double 타입은 부동 소수점 연산에 쓰이며, 넓은 범위의 수를 빠르게 정밀한 근사치로 계산하도록 설계되었다.

float와 double 타입은 특히 금융 계산과는 맞지 않는다.

🍑 본론

✅ example

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을 사용하는 것이 좋다.

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

✅ 단점

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

BigDecimal의 대안으로 int 혹은 long 타입을 쓸 수 있지만, 그럴 경우 다를 수 있는 값의 크기가 제한되고, 소수점을 직접 관리해야 한다.

⭕ 대안으로 달러 대신 센트로 구현하면 된다(?) 이게 맞나..

public static void main(String[] args) {
    int itemBought = 0;
    int funds = 100;

    for (int price = 10; funds >= price; price += 10) {
        funds -= price;
        itemBought++;
    }

    System.out.println(itemBought + "개 구입");
    System.out.println("잔돈(달러): " + funds);
}

🍑 결론

정확한 답이 필요하다면 float나 double 대신 BigDecimal을 사용하라.

불편함이나 성능 저하가 있을 수 있다는 단점이 있지만, 정확한 계산을 할 수 있다.

반면, 성능이 중요하고 소수점을 직접 추적할 수 있고 숫자가 너무 크지 않다면 int나 long을 사용하라.


Referenced by

-

youngkimi commented 5 months ago

위 수식이 틀린 이유는? (개발자 면접 타임)