개요
개발을 하다 보면 소수 계산이 필요한 경우가 자주 있다. 처음에는 double이나 float 같은 기본 자료형을 사용했었는데, 이러한 자료형은 금액대가 커질수록 오차가 나는 것을 체감할 수 있다. 가격 계산이나 금액과 관련된 도메인을 다룰 때, 이러한 오차는 치명적일 수 있으므로 자바에서 제공하는 BigDecimal이라는 클래스를 사용하고 있는데 이 클래스가 기존에 사용하던 클래스와 어떤 부분이 다른지 정리하고자 한다.
BigDecimal의 필요성
자바의 double과 float는 부동소수점 연산을 사용해 실수를 처리한다. 이는 빠른 계산을 가능하게 하지만, 미세한 소수점 이하 자리에서 오차가 발생할 수 있다. 특히 금융 관련 애플리케이션에서는 이런 작은 오차도 큰 문제가 될 수 있다. 따라서 정확한 소수 계산이 필요한 경우에는 BigDecimal을 사용하는 것이 바람직하다.
double과 BigDecimal의 차이
double과 BigDecimal은 둘 다 소수를 다룰 수 있지만, 그 동작 방식은 매우 다르다. double은 부동소수점을 사용해 내부적으로 근사값을 저장하기 때문에 연산 과정에서 오차가 발생할 수 있다. 반면 BigDecimal은 문자열로 숫자를 저장하여 정확한 계산을 보장한다.
public class BigDecimalExample {
public static void main(String[] args) {
double a = 0.1;
double b = 0.2;
double result = a + b;
System.out.println("double 결과: " + result); // 출력: 0.30000000000000004
BigDecimal bigA = new BigDecimal("0.1");
BigDecimal bigB = new BigDecimal("0.2");
BigDecimal bigResult = bigA.add(bigB);
System.out.println("BigDecimal 결과: " + bigResult); // 출력: 0.3
}
}
위 코드에서 보듯이, double 연산에서는 예상하지 못한 오차가 발생하지만 BigDecimal을 사용하면 정확한 값이 나온다.
BigDecimal 사용 예시
BigDecimal은 정확한 계산을 보장하지만, 다루기가 조금 까다롭다. 특히 생성할 때는 new BigDecimal("숫자")와 같이 문자열을 사용하는 것이 중요하다. 만약 new BigDecimal(0.1)과 같이 double을 그대로 넣으면, double의 부동소수점 문제로 인해 오차가 포함된 값이 생성된다.
또한, BigDecimal을 사용해 연산할 때는 add(), subtract(), multiply(), divide() 메서드를 사용해야 한다. 단순한 +, -, *, / 연산자는 지원하지 않기 때문에 익숙해지는 것이 중요하다.
BigDecimal value1 = new BigDecimal("1.05");
BigDecimal value2 = new BigDecimal("2.55");
BigDecimal sum = value1.add(value2); // 덧셈
BigDecimal difference = value1.subtract(value2); // 뺄셈
BigDecimal product = value1.multiply(value2); // 곱셈
BigDecimal quotient = value1.divide(value2, RoundingMode.HALF_UP); // 나눗셈 (반올림 모드 설정 필요)
위 예시에서는 BigDecimal의 다양한 연산 방법을 보여준다. 나눗셈의 경우 반올림 모드를 지정해야 정상적으로 작동하므로, 추가적인 설정이 필요할 수 있다.
정리
BigDecimal은 자바에서 정확한 소수 계산을 위해 반드시 사용해야 하는 클래스이다. 특히 금융, 회계 등과 같은 분야에서 double이나 float의 오차는 큰 문제를 일으킬 수 있기 때문에, 이런 부분을 명확하게 처리하려면 BigDecimal을 사용하는 것이 좋다. 다만 사용법이 조금 까다로울 수 있으니, 필요한 메서드와 특징을 잘 숙지하는 것이 중요하다.
'TIL' 카테고리의 다른 글
[Redis] SET 값 조회 및 삭제하기 (0) | 2024.09.27 |
---|---|
[Java] Stream API의 효율적인 사용법과 주의할 점 (0) | 2024.09.25 |
자바 객체의 equals()와 hashCode() 오버라이드 시 주의할 점 (1) | 2024.09.22 |
[Java] 향상된 try catch문: try-with-resources (0) | 2024.09.21 |
프로메테우스란? (0) | 2023.03.01 |
댓글