java.math.BigDecimal의 바른 사용에 대해서-2
![]()
또 쏘장입니다.
이전 글에서도 언급을 했지만 개발시 계산을 할 때 보통 primitive date type을 사용해서 계산을 하고, 아주 정확한 계산을 할 때 java.math.BigDecimal을 사용한다고 했습니다.
오늘도 정확한 계산을 위해 사용하는 BigDecimal을 잘 못 사용하고 있는 경우를 발견해서 이전글과 연결하여 포스팅 해봅니다.
만일 다음과 같은 값이 있다고 가정을 하고 나누기를 해봅니다.
double d1 = 1.0;
double d2 = .3;
d1 / d2 ==> 3.3333333333333335라는 결과가 나옵니다.(이건 제 노트북에서 나온 값이구요. 다른시스템 다른 OS에서는 다른 값이 나올 수도 있습니다.)
이상 없군요. ^^;
이제 동일한 값을 BigDecimal로 처리해봅시다.
BigDecimal b1 = BigDecimal.valueOf(1.0);
BigDecimal b2 = BigDecimal.valueOf(.3);
b1.divide(b2);
==> java.lang.ArithmeticException을 토해내는군요. (Non-terminating decimal expansion; no exact representable decimal result.)
이유는 계산에 끝이 보이지 않기 때문이라지요. 3.33333333333333333333333333333.....이 무한으로 나가는 경우입니다.
이런 경우가 자주 발생하지 않는 경우라도 한 번 발생하면 대책이 없지요. 소위 말하는 "시.한.폭.탄"이라고나 할까요.
오늘 발견한 잘 못 사용한 예도 바로 이 경우였습니다.
어 쩌다 한 번 나올까 말까한 로직에서 나와버린 거지요. ^^;
그러면 어떻게 하면 될까요.
BigDecimal을 사용해서 나누기(java.math.BigDecimal#divide())를 할 때는 반드시 소수 몇 째자리까지 계산을 할 것인지 지정을 해주어야 합니다.
아래와 같이 말이지요.
b1.divide(b2, MathContext.DECIMAL32); 처럼요.
MathContext에는 static으로 DECIMAL32,64,128이 선언이 되어있고 정밀도는 32-7, 64-16, 128-34로 지정이 되어있습니다. 만일 그 이상의 정확도를 요하는 경우라면 직접 new MathContext(256)처럼 정밀도를 지정해주시면 됩니다.
BigDecimal을 이용한 나누기 얘기가 나온김에 나누기에 관한 method도 한 번 살펴봅시다.
- b1.divide(b2,
BigDecimal.ROUND_HALF_UP);
이경우는 수수자리는 버려진다고 보시면 됩니다. round mode는 BigDecimal의 상수를 참조하세요. - b1.divide(b2,
RoundingMode.HALF_UP);
RoundingMode enum에서 사용하는 상수는 BigDecimal에 정의 된 상수와 같습니다. 살펴보니. HALF_UP(BigDecimal.HALF_UP)으로 되어 있더군요. - b1.divide(b2,
MathContext.DECIMAL32);
정밀도를 계산결과 소수 6자리로 지정한 경우입니다. 이 경우는 3.333333이 나오겠지요.
정밀도는 이전에 언급 된 내용을 참고하세요. - b1.divide(b2, new
MathContext(256));
이 경우는 정밀도를 직접 지정한 경우입니다. - b1.divide(b2, 16,
BigDecimal.ROUND_HALF_UP);
이 경우는 소수 16자리까지 scale을 하는 경우입니다. 소수 17자리에서 반올림됩니다. - b1.divide(b2, 16,
RoundingMode.HALF_UP));
위의 경우와 같습니다. 다만 rounding mode를 enum으로 사용하고 있을 뿐입니다.
이상으로 java.math.BigDecimal#divide()에 대해 살펴보았습니다.
뭐든지 잘 쓰면 약이 되고 잘 못 쓰면 독이됩니다.
항상 명심하시고 개발해주시길 바랍니다.
오늘도 즐거운 하루 보내시길...
이상 쏘장이었습니다.
[출처] java.math.BigDecimal 의 바른 사용에 대해서-2|작성자 아론
