Java BigDecimal 메서드 완전 정리: add, multiply, divide, compareTo 사용법
BigDecimal은 Java에서 금액, 정밀한 소수 계산을 처리할 때 반드시 써야 하는 핵심 클래스입니다. 하지만 메서드가 너무 많아서 어떤 메서드를 언제 써야 하는지 헷갈리기 쉽죠.
이 글에서는 공식 문서의 Method Summary를 기준으로, 자주 쓰는 BigDecimal 메서드를 카테고리별로 정리하고 실제 실무에서 어떻게 활용하는지 예제와 함께 설명합니다.
1. BigDecimal이 필요한 이유 및 기본 개념
double, float은 이진 부동소수점이기 때문에
금액·정밀 계산에 오차가 발생합니다.
예를 들어, 세금·수수료·환율 계산처럼 소수점 자릿수와 반올림이 중요한 곳에서는
반드시 BigDecimal을 사용해야 합니다.
- 정밀도(precision) : 전체 유효 자릿수
- 스케일(scale) : 소수점 이하 자릿수 (예: 123.45 → scale = 2)
아래에서 나오는 많은 메서드 설명에 scale(), precision()이 등장하므로
개념을 알고 있으면 이해가 훨씬 쉽습니다.
2. 핵심 연산 메서드: add, subtract, multiply, divide
가장 많이 쓰는 연산 메서드는 다음과 같습니다. (빨간색으로 표시된 것이 특히 중요)
2-1. 더하기 – add()
BigDecimal add(BigDecimal augend)
⇒ (this + augend), scale은max(this.scale(), augend.scale())BigDecimal add(BigDecimal augend, MathContext mc)
⇒ 더하기 결과에MathContext기준으로 반올림·정밀도 적용
2-2. 빼기 – subtract()
BigDecimal subtract(BigDecimal subtrahend)
⇒ (this - subtrahend), scale은 두 값 중 더 큰 scale 사용BigDecimal subtract(BigDecimal subtrahend, MathContext mc)
⇒ 반올림·정밀도 제어 포함
2-3. 곱하기 – multiply()
-
BigDecimal multiply(BigDecimal multiplicand)
⇒ (this × multiplicand),scale = this.scale() + multiplicand.scale() BigDecimal multiply(BigDecimal multiplicand, MathContext mc)
⇒ 곱셈 결과에MathContext기반 반올림 적용
2-4. 나누기 – divide()
BigDecimal에서 가장 많이 터지는 예외가 바로 divide()입니다.
(무한 소수인 경우 ArithmeticException) 메서드 오버로드를 제대로 이해하는 것이 중요합니다.
-
BigDecimal divide(BigDecimal divisor)
⇒ (this / divisor),preferred scale = this.scale() - divisor.scale()
정확한 몫을 표현할 수 없으면ArithmeticException발생 BigDecimal divide(BigDecimal divisor, int roundingMode)BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode)
⇒ 나눗셈 결과가 무한 소수인 경우, 지정한 반올림 모드로 처리BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
⇒ 결과의 소수 자릿수(scale)를 직접 지정 + 반올림 모드 결정BigDecimal divide(BigDecimal divisor, MathContext mc)
⇒ 전체 정밀도·반올림을MathContext로 제어
2-5. 간단 예제
// 금액 계산 예시
BigDecimal price = new BigDecimal("1000.00");
BigDecimal qty = new BigDecimal("3");
BigDecimal amount = price.multiply(qty); // 3000.00
// 10% 할인
BigDecimal discountRate = new BigDecimal("0.10");
BigDecimal discount = amount.multiply(discountRate); // 300.0000
BigDecimal pay = amount.subtract(discount); // 2700.0000
// 소수 둘째 자리까지 반올림
pay = pay.setScale(2, RoundingMode.HALF_UP); // 2700.00
3. 비교·부호 관련 메서드: compareTo, equals, signum, abs, negate, plus
3-1. 비교 – compareTo() vs equals()
-
int compareTo(BigDecimal val)
⇒ this < val → 음수, this == val → 0, this > val → 양수
값만 비교하며, scale이 달라도 값이 같으면 0 (예: 1.0 과 1.00 은 동일) -
boolean equals(Object x)
⇒ 값 + scale까지 모두 비교 (1.0 ≠ 1.00)
3-2. 절대값·부호 – abs(), signum(), negate(), plus()
BigDecimal abs(),BigDecimal abs(MathContext mc)– 절대값int signum()– 음수(-1), 0, 양수(1) 반환BigDecimal negate(),negate(MathContext mc)– 부호 반전(-this)-
BigDecimal plus(),plus(MathContext mc)
⇒ (+this), 특별한 연산은 없지만MathContext를 적용하고 싶을 때 사용
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("1.00");
System.out.println(a.equals(b)); // false
System.out.println(a.compareTo(b)); // 0
BigDecimal negative = new BigDecimal("-123.45");
System.out.println(negative.abs()); // 123.45
System.out.println(negative.signum()); // -1
4. 나눗셈·나머지 메서드: divideToIntegralValue, divideAndRemainder, remainder
4-1. 정수부만 – divideToIntegralValue()
BigDecimal divideToIntegralValue(BigDecimal divisor)BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc)
⇒ (this / divisor)의 정수 부분만 반환합니다. (소수점 이하 버림)
4-2. 몫과 나머지를 동시에 – divideAndRemainder()
BigDecimal[] divideAndRemainder(BigDecimal divisor)BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc)
⇒ [0] = 몫, [1] = 나머지 를 담은 BigDecimal[]을 반환합니다.
4-3. 나머지만 – remainder()
BigDecimal remainder(BigDecimal divisor)BigDecimal remainder(BigDecimal divisor, MathContext mc)
⇒ (this % divisor)를 BigDecimal로 반환합니다.
BigDecimal ten = new BigDecimal("10");
BigDecimal three = new BigDecimal("3");
BigDecimal[] qr = ten.divideAndRemainder(three);
System.out.println("몫: " + qr[0]); // 3
System.out.println("나머지: " + qr[1]); // 1
5. 스케일·정밀도 관련 메서드: scale, precision, setScale, stripTrailingZeros
5-1. scale(), precision()
int scale()– 소수점 이하 자릿수int precision()– 전체 유효 자릿수
5-2. 소수 자릿수 조정 – setScale()
BigDecimal setScale(int newScale)BigDecimal setScale(int newScale, int roundingMode)BigDecimal setScale(int newScale, RoundingMode roundingMode)
⇒ 지정한 newScale로 스케일을 맞추면서, 필요할 경우 반올림을 수행합니다.
예: 금액을 항상 소수 둘째 자리까지 맞추고 싶을 때 자주 사용.
5-3. 소수점 이동 – movePointLeft()/movePointRight(), scaleByPowerOfTen()
BigDecimal movePointLeft(int n)– 소수점 왼쪽으로 n자리 이동BigDecimal movePointRight(int n)– 소수점 오른쪽으로 n자리 이동BigDecimal scaleByPowerOfTen(int n)–this * 10^n
5-4. 불필요한 0 제거 – stripTrailingZeros()
BigDecimal stripTrailingZeros()
⇒ 값은 그대로 두고, 표현상의 뒤쪽 0을 제거합니다. (예: 1.2300 → 1.23)
BigDecimal val = new BigDecimal("123.4500");
System.out.println(val.scale()); // 4
System.out.println(val.stripTrailingZeros()); // 123.45
6. 기본 타입·문자열 변환 메서드: valueOf, intValue, toPlainString 등
6-1. 기본 타입 변환
int intValue(),long longValue(),float floatValue(),double doubleValue()int intValueExact(),long longValueExact(),short shortValueExact(),byte byteValueExact()
⇒ 소수점 이하가 0이 아닌 경우 예외를 던져서, 정보 손실 여부를 체크합니다.
6-2. BigInteger 변환
BigInteger toBigInteger()BigInteger toBigIntegerExact()BigInteger unscaledValue()– 스케일을 적용하기 전의 정수 값
6-3. 문자열 표현
String toString()– 필요시 과학적 표기(지수) 사용String toPlainString()– 지수 없이 평범한 소수 형태String toEngineeringString()– 엔지니어링 표기법 사용
6-4. valueOf() 팩토리 메서드
static BigDecimal valueOf(long val)static BigDecimal valueOf(double val)static BigDecimal valueOf(long unscaledVal, int scale)
주의: new BigDecimal(double) 생성자는 이진 부동소수점 특성 때문에
예상치 못한 값이 나올 수 있습니다.
금액처럼 정확한 값이 중요할 때는 항상
new BigDecimal("1000.00") 또는 BigDecimal.valueOf(1000L) 패턴을 권장합니다.
7. 실무에서 자주 쓰는 BigDecimal 패턴 예제
7-1. 안전한 생성 패턴
// 좋지 않은 예 (double 직접 사용)
BigDecimal bad = new BigDecimal(0.1);
// 좋은 예 (문자열 또는 valueOf 사용)
BigDecimal good1 = new BigDecimal("0.1");
BigDecimal good2 = BigDecimal.valueOf(0.1); // 내부적으로 문자열 기반 처리
7-2. 금액 + 부가세 계산
BigDecimal supply = new BigDecimal("100000"); // 공급가
BigDecimal vatRate = new BigDecimal("0.1"); // 10%
BigDecimal vat = supply.multiply(vatRate); // 10000.0
BigDecimal total = supply.add(vat); // 110000.0
// 항상 두 자리로 반올림
vat = vat.setScale(0, RoundingMode.HALF_UP);
total = total.setScale(0, RoundingMode.HALF_UP);
7-3. 정렬·비교시 compareTo() 사용
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("1.00");
// 정렬/크기 비교에는 compareTo() 사용
if (a.compareTo(b) == 0) {
System.out.println("값은 같다.");
}
댓글
댓글 쓰기