float와 double의 문제점
- float와 double 타입은 과학과 공학 계산용으로 설계되었다.
- 이진 부동소수점 연산에 쓰이며, 넓은 범위의 수를 빠르게 정밀한 '근사치'로 계산하도록 세심하게 설계되었다.
- 따라서 정확한 결과가 필요할 때는 사용하면 안 된다.
- float와 double 타입은 특히 금융 관련 계산과는 맞지 않는다.
- 0.1 혹은 10의 음의 거듭제곱 수(10^-1)를 표현할 수 없기 때문이다.
ex1) 주머니에 1.03 달러가 있는데 그중 42 센트를 썼다.
System.out.println(1.03 - 0.42)는 0.6100000000000001을 출력한다.
ex2) 주머니에 1 달러가 있는데 10센트 사탕 9개를 샀다.
System.out.println(1.00 - 9*0.10)는 0.09999999999999998을 출력한다.
ex3) 주머니에 1달러가 있고, 선반에 10센트부터 1 달러 짜리 사탕이 있을 때 10센트짜리부터 하나씩 살 수 있을 때까지 사는 프로그램을 만들어보자
금융 계산에 부동소수 타입 사용
- 정답은 사탕 4개를 구입하고 잔돈이 0원이지만, 사탕 3개를 구입한 후 잔돈이 0.39999999999.. 달러로 출력된다.
BigDecimal, int, long을 이용한 해법
금융 계산에는 BigDecimal, int 혹은 long을 사용해야 한다.
BigDecimal을 사용한 해법
- BigDecimal 생성자 중 문자열을 받는 생성자는 계산 시 부정확한 값이 사용되는 것을 막기 위한 조치다.
- 사탕 4개를 구입한 후 잔돈 0달러가 남는다는 정답이 도출된다.
- 기본 타입보다 쓰기 훨씬 불편하고, 훨씬 느리다.
정수 타입을 사용한 해법
- 모든 계산을 달러 대신 센트로 수행한다.
- 다룰 수 있는 값의 크기가 제한되고, 소수점을 직접 관리해야 한다.
결론
- 정확한 답이 필요한 계산에는 float나 double은 피하자.
- 소수점 추적은 시스템에 맡기고, 코딩 시의 불편함이나 성능 저하를 신경 쓰지 않겠다면 BigDecimal을 사용하자.
- BigDecimal은 반올림을 완벽히 제어할 수 있다.
- 성능이 중요하고 소수점을 직접 추적할 수 있고 숫자가 너무 크지 않다면 int나 long을 사용하자.
- 숫자를 9자리 십진수로 표현할 수 있다면 int를, 18자리 십진수로 표현할 수 있다면 long을 사용하자.
- 18자리를 넘어가면 BigDecimal을 사용해야 한다.
'Java > Effective Java' 카테고리의 다른 글
[Effective Java] Item 62. 다른 타입이 적절하다면 문자열 사용을 피하라 (0) | 2023.07.30 |
---|---|
[Effective Java] Item 61. 박싱된 기본 타입보다는 기본 타입을 사용하라 (0) | 2023.07.30 |
[Effective Java] Item 59. 라이브러리를 익히고 사용하라 (0) | 2023.07.23 |
[Effective Java] Item 58. 전통적인 for 문보다는 for-each 문을 사용하라 (0) | 2023.07.23 |
[Effective Java] Item 57. 지역변수의 범위를 최소화하라 (0) | 2023.07.22 |