요약
•
float과 double에는 부동 소수점으로 인한 오차가 발생하니, 금융 계산과 같이 정확한 계산이 필요한 곳에는 사용하지 말자.
정확한 계산에는 double과 float 사용 피하기
•
float과 double은 이진 부동소수점 연산으로 넓은 범위의 수를 빠르게 정밀한 근사치로 계산하도록 과학과 공학 계산용으로 설계되었다. 하지만 이런 부동소수점의 오차 때문에 double과 float은 금융 관련 계산과는 맞지 않는다.
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.prlntln("잔돈(달러) :" + funds) ;
}
Java
복사
•
위 프로그램을 실행하면 아이템을 3개 구입한 이후에 0.399999999999999가 남아 다음 아이템을 구매하지 못한다. 이렇게 오차가 발생하기 때문에, 금융 계산에는 BigDecimal, int 혹은 long을 사용해야한다.
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.prlntln("잔돈(달러) :" + funds) ;
}
Java
복사
•
이렇게 BigDecimal을 사용하여 코드를 바꾸면, 위에서는 아이템을 4개 구입 후 잔돈이 0이 남는다.
•
하지만 BigDecimal은 기본 타입보다 쓰기가 불편하고 훨씬 느리다. 이에 대안으로 int나 long을 사용하여 소수점을 직접 관리하는 것도 하나의 방법이다. 금융 계산이라면 아래처럼 금액의 최소 단위를 맞추어 계산할 수 있다.
public static void main(String[] args) {
int funds = 100;
int itemsBought = 0;
for (double price = 10; funds >= price; price += 10) {
funds -= price;
itemsBought++;
}
System.out.println(itemsBought + "개 구입");
System.out.prlntln("잔돈(달러) :" + funds) ;
}
Java
복사