IT/Programming / / 2023. 4. 26. 13:37

<Effective Java> RULE 48 정확한 답이 필요하다면 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
 

Q. 1달러의 돈이 있을 때 10센트, 20센트, 30센트, 가장 비싼건 1달러 짜리의 사탕을 사려고하는데

가장 싼 사탕부터 시작해서 가장 비싼걸 사갈 때 얼마나 많은 사탕을 살 수 있고 거스름 돈은 얼마인가?

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을 사용해야 한다.

final BigDecimal TEN_CENTS = new BigDecimal("0.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에는 두가지 문제가 있다.

· 기본 산술 연살 자료형보다 사용이 불편하며 느리다.

ㄴ 대안으로 int나 long을 사용

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
 

결론

· 정확한 답을 요구하는 뭄제를 풀 때 float나 double을 사용하지 말라.

· 소수점 이하 처리는 알아서, 기본 자료형 보다 사용이 불편하고 조금 느려도 괜찮으면 BigDecimal을 사용해라.

ㄴ BigDecimal은 올림연산에 8가지 모드가 있다.

· 성능이 중요하고 소수점 아래 수를 직접 관리해도 상관이 없으면(계산할 수가 크지 않을 경우) int를 사용하라.

· 18개 이하로 표현 가능할 때는 long을 사용하고 그 이상일 때는 BigDecimal을 사용하라.

 

 

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유