Book/Effective Java
[교재 EffectiveJava] 아이템 60. 정확한 답이 필요하다면 float와 double은 피하라
shbada
2021. 12. 2. 00:36
728x90
반응형
float와 double 타입의 단점
float 와 double 타입은 과학과 공학 계산용으로 설계되었다. 이는 정확한 결과가 필요할 때는 사용하면 안된다. float와 double 타입은 특히 금융 관련 계산과는 맞지 않는다. 0.1 혹은 10의 음의 거듭제곱수 등을 표현할 수 없기 때문이다.
오류 발생하는 코드
package com.java.effective.item60;
public class Main {
public static void main(String[] args) {
double funds = 1.00;
int itemBought = 0;
for (double price = 0.10; funds >= price; price += 0.10) {
funds = funds - price;
itemBought++;
}
System.out.println(itemBought + "개 구입");
System.out.println("잔돈(달러):" + funds);
}
}
금융 계산에 부동소수 타입을 사용했다. 이는 결과가 아래와 같다.
결과
3개 구입
잔돈(달러):0.3999999999999999
이는 잘못된 결과다. 이 문제를 올바로 해결하려면, BigDecimal, int 혹은 long을 사용해야한다.
BigDecimal 사용으로 변경
BigDecimal 로 변경
package com.java.effective.item60;
import java.math.BigDecimal;
public class Main2 {
public static void main(String[] args) {
final BigDecimal TEN_CNETS = new BigDecimal("0.10");
int itemsBought = 0;
BigDecimal funds = new BigDecimal("1.00");
for (BigDecimal price = TEN_CNETS;
funds.compareTo(price) >= 0; price = price.add(TEN_CNETS)) {
funds = funds.subtract(price);
itemsBought++;
}
System.out.println(itemsBought + "개 구입");
System.out.println("잔돈(달러): " + funds);
}
}
위 코드는 아래 결과와 같이 올바른 답이 나온다.
결과
4개 구입
잔돈(달러): 0.00
BigDecimal의 단점
기본 타입보다 훨씬 쓰기 불편하고, 훨씬 느리다. BigDecimal의 대안으로 int 혹은 long 타입을 쓸 수도 있다. 그럴 경우 다룰 수 있는 값의 크기가 제한되고, 소수점을 직접 관리해야 한다. 이번 예시는 달러 대신 센트로 수행하면 훨씬 빠르고 편리하게 구현할 수 있다.
int 타입
package com.java.effective.item60;
import java.math.BigDecimal;
public class Main3 {
public static void main(String[] args) {
int itemsBought = 0;
int funds = 100;
for (int price = 10; funds >= price; price += 10) {
funds = funds - price;
itemsBought++;
}
System.out.println(itemsBought + "개 구입");
System.out.println("잔돈(달러): " + funds);
}
}
결과
4개 구입
잔돈(달러): 0
상황에서의 선택
1) int
숫자를 아홉자리 십진수로 표현할 수 있을 경우
2) long
열여덟 자리 십진수로 표현할 수 있을 경우
3) BigDecimal
열여덟 자리를 넘어가는 경우
반응형