티스토리 뷰
반응형
float와 double 연산은 정확하지 않다. (특히 금융 관련 계산과는 맞지 않음)
double result = 1.03 - 0.42;
System.out.println(result); // 0.6100000000000001
위와 같은 단순한 계산에도 오차가 발생한다. → float와 double은 부동소수점 방식을 사용하기 때문
부동소수점 방식
부동소수점 방식은 수를 정수와 실수로 구분하지 않고 지수부와 가수부로 구분한다.
소수점이 고정되지 않기 때문에 더 폭넓은 범위를 표현할 수 있지만, 필연적으로 오차가 발생하여 근사값을 구한다.
해결 방법
1) BigDecimal
double 타입을 BigDecimal 을 사용하면 실수 연산을 오차없이 사용할 수 있다.
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);
}
2) int 혹은 long
BigDecimal의 대안으로 int 나 long을 쓸 수도 있다.
이 방법은 연산도 정확하고 편리하고 빠르다.
그러나 다룰 수 있는 값의 크기가 제한되고, 소수점을 직접 관리해야한다.
ex) 0.1 달러 = 10 센트
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);
}
결론
정확한 답이 필요할 때는 float나 double은 피하라.
소수점 추적은 시스템에 맡기고 성능 저하나 불편함은 신경쓰지 않는다면 BigDecimal을 사용하라. (반올림 완벽히 제어 가능)
반면, 소수점을 직접 추적할 수 있고 성능이 중요하고 숫자가 너무 크지 않다면 int나 long을 사용하라.
숫자를 아홉자리 십진수로 표현할 수 있다면 int, 열여덟자리 십진수로 표현할 수 있다면 long을 사용하라.
이를 넘어가면 BigDecimal을 사용해야함
반응형
'Java > Effective Java' 카테고리의 다른 글
[Effective Java] 62.다른 타입이 적절하다면 문자열 사용을 피하라 (0) | 2022.04.08 |
---|---|
[Effective Java] 61.박싱된 기본 타입보다는 기본 타입을 사용하라 (0) | 2022.04.08 |
[Effective Java] 59.라이브러리를 익히고 사용하라 (0) | 2022.04.06 |
[Effective Java] 58.전통적인 for 문보다는 for-each문을 사용하라 (0) | 2022.04.06 |
[Effective Java] 57.지역변수의 범위를 최소화하라 (0) | 2022.04.06 |
댓글