JAVA/Effective Java

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

꾸준함. 2024. 3. 17. 08:36

float과 double 자료형은 부동소수점 연산에 쓰이며, 넓은 범위의 수를 빠르게 정밀한 `근사치`를 계산하도록 설계되었습니다.

따라서 위 자료형은 정확한 결과가 필요할 때에는 절대 사용해서는 안됩니다.

  • 이 때문에 float과 double 자료형은 금융 관련 계산과는 성격이 맞지 않으며 지양해야 함

 

1. double 자료형의 계산 결과가 정확하지 않은 예제 코드

 

 

코드 부연 설명

  • $0.1, $0.2, $0.3, $0.4 달러의 물건을 샀을 것이라고 예상했고 이에 따라 잔돈 또한 없을 것이라고 예상
  • 하지만 부동소수점 연산 때문에 0.3 + 0.1의 결과가 0.41이 됨
    • 이 때문에 예산인 $1을 넘어 잔돈으로 $0.39999999999999999가 반환

 

  • 올바른 결과 출력을 위해서는 BigDecimal 사용을 권장

 

2. BigDecimal을 사용한 코드

 

 

코드 부연 설명

  • 예상한대로 $0.1, $0.2, $0.3, $0.4 물건을 샀고 잔돈은 없음
  • 하지만 BigDecimal에는 단점 존재
    • primitive 타입보다 쓰기가 훨씬 불편하고 느림
    • 단발성 계산이라면 문제가 없지만 지속적으로 사용되는 연산일 경우 성능에 영향을 줄 수 있음
    • BigDecimal의 대안으로 int, long 자료형을 사용할 수 있지만 소수점을 직접 관리해야 하는 애로사항 존재

 

3. int를 사용한 코드


 

코드 부연 설명

  • 오류를 발생시킬 수 있는 소숫점 제거를 위해 숫자에 100씩 곱함
  • int와 long과 같은 primitive 타입을 사용하면 BigDecimal보다 깔끔하고 정확한 답을 구할 수 있음
  • 그러나 소수점 이하의 숫자를 관리해야 하므로 관리 포인트가 증가하는 단점이 있음
    • 차라리 BigDecimal 사용하는 것을 권장

 

정리

  • 정확한 답이 필요한 계산에는 float나 double을 피해야 함
  • 소수점 추적은 시스템에 맡기고 코딩 시의 불편함이나 성능저하가 중요하지 않다면 BigDecimal을 사용하는 것을 권장
    • BigDecimal은 8가지 반올림 모드를 제공하므로 반올림을 거의 완벽하게 제어 가능

 

  • 성능이 중요하고 소수점을 직접 추적할 수 있고 숫자가 너무 크지 않다면 int나 long을 사용하는 것을 권장
    • 숫자를 9자리 10진수로 표현한다면 int를 사용
    • 숫자를 18자리 10진수로 표현할 수 있다면 long을 사용
    • 숫자가 18자리가 넘어가면 BigDecimal을 사용

 

참고

이펙티브 자바

반응형