BE/Java

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

멍목 2022. 11. 25. 22:51
반응형

EFFECTIVE JAVA(이펙티브 자바)

 

이 포스팅에서 작성하는 내용은 EFFECTIVE JAVA(이펙티브자바) 에서 발췌하였습니다.


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

 

float, double

  • 과학과 공한 계산용으로 설계된 데이터 타입이다.
  • 이진 부동소수점 연산에 쓰이며, 넓은 범위의 수를 빠르게 정밀한 근사치로 계산하도록 설계되었다.
  • 정확한 결과가 필요한 금융 관련 계산과는 어울리지 않는다.
    • 1.03 - 0.42의 결과를 0.6100000000001을 출력한다.

 

 

ex 1) 금융 계산 시에 부동소수 타입을 사용한 잘못된 예

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.39999999999999999
  • 이렇듯 부동소수 타입을 이용하면 정확한 계산 결과가 나오지 않기 때문에,
    금융 계산에는 BigDecimal, int 혹은 long을 사용해야 한다.

 

 

ex 2) ex 1의 예를 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
  • 금융 관련 계산에서 BigDecimal을 사용하면 정확한 결과를 도출할 수 있다.
  • 다만, 기본 타입보다 쓰기가 훨씬 불편하고, 느리다.

 

 

ex 3) ex 1의 예를 int로 구현한 예

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);
}
  • BigDecimal의 대안으로 int 혹은 long 타입을 사용할 수 있다.
  • 대신 다룰 수 있는 값의 크기가 제한되고, 소수점을 직접 관리해야한다.
  • 이 경우에는 모든 계산을 달러 대신 센트로 수행하도록 로직을 수정하였다.

 

 

정리

  • 정확한 계산이 필요할 때에는 float과 double을 사용하지 말자.
  • 대신, BigDecimal이나 int, long을 이용하자.
  • BigDecimal은 사용하기 불편하고 성능 저하가 발생하지만, 다양한 기능을 제공하니 참고하자.
반응형