JAVA BigDecimal 사칙연산(더하기, 빼기, 나누기, 곱하기), 비교 compareTo, 소수점 처리 (올림, 버림, 반올림)

 

자주 사용되는 BigDecimal 클래스에 대해서 정리해 놓으려 한다.

 

매번 사용되지는 않지만 실수의 정확한 연산이 필요할 경우 사용한다.

 

빈번하게 사용되는 다른 데이터 타입과는 다르게

 

정확한 계산이 필요한 경우에만 BigDecimal을 사용하다 보니

 

사칙연산이나 비교, 소수점을 처리할 때 자꾸만 검색을 하게 된다 ㅠㅠ

 

또한 검색하다보니 잘못 정리된 내용들이 많아 이참에 정리를 해두는 것이 좋다고 생각해서

 

정리해 보려고 한다.

 

 



 

1. 사칙연산

더하기, 빼기, 곱하기, 나누기는 각각

add, subtract, multiply, divide 함수를 활용하여 계산할 수 있다.

 

예) 

1
2
3
4
5
6
7
        BigDecimal number1 = new BigDecimal("250.125");
        BigDecimal number2 = new BigDecimal("150.352");
        
        System.out.println("더하기 : " + number1.add(number2));
        System.out.println("빼기   : " + number1.subtract(number2));
        System.out.println("곱하기 : " + number1.multiply(number2));
        System.out.println("나누기 : " + number1.divide(number2));
cs

결과)

1
2
3
4
5
6
더하기 : 400.477
빼기   : 99.773
곱하기 : 37606.794000
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
    at java.math.BigDecimal.divide(BigDecimal.java:1690)
    at bets.module.building.service.BdBalnceAccountsService.main(BdBalnceAccountsService.java:768)
cs

 

결과는 위와 같다.

 

더하기, 빼기, 곱하기는 특별한 이슈없이 결과가 잘 나왔다.

하지만 나누기는 나오지 않고 오류가 났다.

오류 내용을 보니 Non-terminating decimal expansion; no exact representable decimal result. 라고 되어있는데

소수점을 지정하지 않아서 정확한 계산을 할 수 없다는 내용이다.

 

그래서 나누기는 다음과 같이 소수점 처리를 해주어야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
        BigDecimal number1 = new BigDecimal("250.125");
        BigDecimal number2 = new BigDecimal("150.352");
        
 
        System.out.println("나누기 : " + number1.divide(number2, BigDecimal.ROUND_UP));
        System.out.println("나누기 : " + number1.divide(number2, BigDecimal.ROUND_DOWN));
        System.out.println("나누기 : " + number1.divide(number2, BigDecimal.ROUND_HALF_UP));
        System.out.println("나누기 : " + number1.divide(number2, BigDecimal.ROUND_HALF_DOWN));
        
        System.out.println("나누기 : " + number1.divide(number2, 4, BigDecimal.ROUND_UP));
        System.out.println("나누기 : " + number1.divide(number2, 4, BigDecimal.ROUND_DOWN));
        System.out.println("나누기 : " + number1.divide(number2, 4, BigDecimal.ROUND_HALF_UP));
        System.out.println("나누기 : " + number1.divide(number2, 4, BigDecimal.ROUND_HALF_DOWN));
cs

 

먼저 첫번째 divide 함수는 파라미터가 2개밖에 없다.

스케일 즉 표시할 소수점 자리수는 생략하였으며 나뉘는 수 (피제수) 의 자리수를 따라간다.

첫번째 파라미터는는 나누는 수(제수) 이고 두번째 파라미터는 roundingMode (소수점 처리 방법) 이다.

 

소수점 처리 방법은 다음과 같다.

BigDecimal.ROUND_UP : 올림

BigDecimal.ROUND_DOWN : 버림

BigDecimal.ROUND_HALF_UP : 반올림 ( 5 이상 올림 )

BigDecimal.ROUND_HALF_DOWN : 반내림 ( 5 이하 내림 )

 

다른 방법도 더 있지만 자주 사용하는 4가지만 설명한다.

 

두번째 divide 함수는 파라미터가 3개이다.

첫번째 파라미터와 마지막 파라미터는 같지만 가운데 int 타입의 파라미터가 하나 더 있다.

이 파라미터의 역할은 스케일을 정하는 역할로 소수점 자리를 어디까지 표현할 것인가를 지정한다.

 

결과 )

1
2
3
4
5
6
7
나누기, 소수점 버림 : 1.663
나누기, 소수점 5이상 올림(반올림) : 1.664
나누기, 소수점 5이하 내림(반내림) : 1.664
나누기, 소수점 올림, 4째자리까지 표시 : 1.6636
나누기, 소수점 버림, 4째자리까지 표시 : 1.6635
나누기, 소수점 5이상 올림(반올림), 4째자리까지 표시 : 1.6636
나누기, 소수점 5이하 내림(반내림), 4째자리까지 표시 : 1.6636
cs

 

 



 

2. 비교 compareTo

BigDecimal 의 비교 방식은 compareTo 라는 함수를 이용해야 한다.

또한 BigDecimal Type 끼리만 비교가 가능하다.

다른 타입일 경우 BigDecimal로 형변환 하여 비교하여야 한다.

일반적인 비교 연산자 ( >, >=, <. <=, ==, != ) 등으로 비교할 수 없다.

 

1
2
3
4
5
6
7
        System.out.println("비교 : " + number1.compareTo(BigDecimal.ZERO));
        System.out.println("비교 : " + number1.compareTo(new BigDecimal("0")));
        
        // 사용방법
        if(number1.compareTo(new BigDecimal("0")) == 1){
            // number1 이 0보다 클 경우
        }
cs

compareTo 함수를 이용하면 return 값이 -1, 0, 1 총 3가지 이다.

 

BigDecimal 의 수치가 val 보다 작으면 -1

BigDecimal 의 수치가 val 와 같으면 0

BigDecimal 의 수치가 val 보다 크면 1

을 리턴한다.
 

 

3. 소수점 처리

BigDecimal 타입의 소수점을 내가 원하는 자리수만큼 표현해야 하는 경우가 있다.

이 경우에는 setScale 함수를 이용한다.

 

1
2
3
4
5
6
        BigDecimal number1 = new BigDecimal("150.35");
        
        System.out.println("소수점 올림 : " + number1.setScale(1, BigDecimal.ROUND_UP));
        System.out.println("소수점 버림 : " + number1.setScale(1, BigDecimal.ROUND_DOWN));
        System.out.println("소수점 5이상 올림(반올림): " + number1.setScale(1, BigDecimal.ROUND_HALF_UP));
        System.out.println("소수점 5이하 내림(반내림): " + number1.setScale(1, BigDecimal.ROUND_HALF_DOWN));
cs

 

원하는 자리수와 roundingMode 를 활용하여 결과를 출력한다.

1
2
3
4
5
소수점 올림 : 150.4
소수점 버림 : 150.3
소수점 5이상 올림(반올림): 150.4
소수점 5이하 내림(반내림): 150.3
 
cs

roundingMode 는 위에서 설명했기 때문에 생략한다.

 

 

 

참고로 다른 블로그들을 보니 roundingMode 에 대해서 잘못 서술한 글들을 많이 볼 수 있었으니 주의하기 바란다.

 

 

 

 

 

 

by 개발자 CofS 2017.11.16 14:24