본문 바로가기
[개발] 언어/Java

JAVA BigDecimal을 왜 그리고 어떻게 사용할까?

by Devsong26 2021. 6. 23.

자바의 수 연산은 기본 자료형이나 BigDecimal 등의 클래스를 이용한다.

 

보통, Double(Wrapper class)와 BigDecimal 중 어떤 것을 사용해야 하는지로 고민하게 된다.

 

기본적인 수 연산은 +, -, *, /, % 연산자를 기본 자료형에 사용하면 될 것인데, 

왜 BigDecimal 등의 숫자 클래스를 사용하여 연산을 수행할까?

 

이와 같은 질문을 스택오버플로우에서 발견하고 답변을 찾았다.

 

A BigDecimal is an exact way of representing numbers. A Double has a certain precision. Working with doubles of various magnitudes (say d1=1000.0 and d2=0.001) could result in the 0.001 being dropped alltogether when summing as the difference in magnitude is so large. With BigDecimal this would not happen.
The disadvantage of BigDecimal is that it's slower, and it's a bit more difficult to program algorithms that way (due to + - * and / not being overloaded).

If you are dealing with money, or precision is a must, use BigDecimal. Otherwise Doubles tend to be good enough.

I do recommend reading the javadoc of BigDecimal as they do explain things better than I do here :)

출처: https://stackoverflow.com/questions/3413448/double-vs-bigdecimal

 

요약하면 더블형 연산은 소수점 연산이 문제가 될 수 있으니, 정확한 소수점 연산을 위해서는 BigDecimal 클래스를 사용하라는 것이다.

 

예시를 보자.

Double d1 = 12345.12347986;
Double d2 = 41235.23498705;

System.out.println("d1 + d2 = " + (d1 + d2)); // d1 + d2 = 53580.358466909995

BigDecimal bd1 = BigDecimal.valueOf(d1);
BigDecimal bd2 = BigDecimal.valueOf(d2);

System.out.println("bd1 = " + bd1);
System.out.println("bd2 = " + bd2);
System.out.println(bd1.add(bd2)); // 53580.35846691

Double형 변수들의 연산 결과는 예상했던 결과와 다른 것을 확인할 수 있다.

 

그러면 어떻게 BigDecimal 을 사용해야 할까?

 


 

BigDecimal

 

BigDecimal API Docs에 소개된 내용의 일부만을 기재합니다.

 

 


 

생성자

 

BigDecimal(BigInteger val)
- Translates a BigInteger into a BigDecimal.

this.paramVal = new BigDecimal(BigInteger.valueOf(100));

 

BigDecimal(BigInteger unscaledVal, int scale)
- Translates a BigInteger unscaled value and an int scale into a BigDecimal.

this.paramValAndScale = new BigDecimal(new BigInteger("-123456789"), 3);

 

BigDecimal(BigInteger unscaledVal, int scale, MathContext mc)
- Translates a BigInteger unscaled value and an int scale into a BigDecimal, with rounding according to the context settings.

this.paramValAndScaleAndMc = new BigDecimal(
                new BigInteger("9876123"), 3,
                new MathContext(7, RoundingMode.HALF_UP));

 

BigDecimal(BigInteger val, MathContext mc)
- Translates a BigInteger into a BigDecimal rounding according to the context settings.

this.paramValAndMc = new BigDecimal(
                new BigInteger("12"),
                new MathContext(1, RoundingMode.HALF_UP));

 

BigDecimal(String val)
- Translates the string representation of a BigDecimal into a BigDecimal.

this.paramString = new BigDecimal("100");

 


 

메소드

 

abs()
- Returns a BigDecimal whose value is the absolute value of this BigDecimal, and whose scale is this.scale().

System.out.println("abs() = " + this.paramValAndScale.abs());

 

add(BigDecimal augend)
Returns a BigDecimal whose value is (this + augend), and whose scale is max(this.scale(), augend.scale()).

System.out.println("add(BigDecimal augend) = " + this.paramVal.add(this.paramValAndScale));

 

compareTo(BigDecimal val)
Compares this BigDecimal with the specified BigDecimal.

System.out.println("compareTo(BigDecimal val) = " + this.paramVal.compareTo(this.paramValAndScale));


divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
Returns a BigDecimal whose value is (this / divisor), and whose scale is as specified.

System.out.println("divide(BigDecimal divisor, int scale, RoundingMode roundingMode) = " + this.paramVal.divide(new BigDecimal("13"), 3, RoundingMode.HALF_UP));

 


divideAndRemainder(BigDecimal divisor)
Returns a two-element BigDecimal array containing the result of divideToIntegralValue followed by the result of remainder on the two operands.

System.out.println("divideAndRemainder(BigDecimal divisor) = " + Arrays.toString(this.paramValAndScaleAndMc.divideAndRemainder(this.paramVal)));


max(BigDecimal val)
Returns the maximum of this BigDecimal and val.

System.out.println("max(BigDecimal val) = " + this.paramValAndScaleAndMc.max(this.paramVal));


min(BigDecimal val)
Returns the minimum of this BigDecimal and val.

System.out.println("min(BigDecimal val) = " + this.paramValAndScaleAndMc.min(this.paramVal));


pow(int n)
Returns a BigDecimal whose value is (thisn), The power is computed exactly, to unlimited precision.

System.out.println("pow(int n) = " + this.paramVal.pow(2));

 


setScale(int newScale, RoundingMode roundingMode)
Returns a BigDecimal whose scale is the specified value, and whose unscaled value is determined by multiplying or dividing this BigDecimal's unscaled value by the appropriate power of ten to maintain its overall value.

System.out.println("setScale(int newScale, RoundingMode roundingMode) = " + this.paramValAndScaleAndMc.setScale(5, RoundingMode.HALF_DOWN));

 


 

Full Source Code

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Arrays;

public class BigDecimalDemo {

    private BigDecimal paramVal, paramValAndScale, paramValAndScaleAndMc, paramValAndMc, paramString;

    public static void main(String[] args){
        BigDecimalDemo demo = new BigDecimalDemo();

        System.out.println("# operateDouble() ");
        demo.operateDouble();
        System.out.println("# ========== #");

        System.out.println("# constructors() ");
        demo.constructors();
        System.out.println("# ========== #");

        System.out.println("# methods() ");
        demo.methods();
        System.out.println("# ========== #");
    }

    private void operateDouble(){
        Double d1 = 12345.12347986;
        Double d2 = 41235.23498705;

        System.out.println("d1 + d2 = " + (d1 + d2)); // d1 + d2 = 53580.358466909995

        BigDecimal bd1 = BigDecimal.valueOf(d1);
        BigDecimal bd2 = BigDecimal.valueOf(d2);

        System.out.println("bd1 = " + bd1);
        System.out.println("bd2 = " + bd2);
        System.out.println(bd1.add(bd2)); // 53580.35846691
    }

    /**
     * BigDecimal(BigInteger val)
     * Translates a BigInteger into a BigDecimal.
     *
     * BigDecimal(BigInteger unscaledVal, int scale)
     * Translates a BigInteger unscaled value and an int scale into a BigDecimal.
     *
     * BigDecimal(BigInteger unscaledVal, int scale, MathContext mc)
     * Translates a BigInteger unscaled value and an int scale into a BigDecimal, with rounding according to the context settings.
     *
     * BigDecimal(BigInteger val, MathContext mc)
     * Translates a BigInteger into a BigDecimal rounding according to the context settings.
     *
     * BigDecimal(String val)
     * Translates the string representation of a BigDecimal into a BigDecimal.
     */
    private void constructors(){
        // BigDecimal(BigInteger val)
        this.paramVal = new BigDecimal(BigInteger.valueOf(100));

        // BigDecimal(BigInteger unscaledVal, int scale)
        this.paramValAndScale = new BigDecimal(new BigInteger("-123456789"), 3);

        // BigDecimal(BigInteger unscaledVal, int scale, MathContext mc)
        this.paramValAndScaleAndMc = new BigDecimal(
                new BigInteger("9876123"), 3,
                new MathContext(7, RoundingMode.HALF_UP));

        // BigDecimal(BigInteger val, MathContext mc)
        this.paramValAndMc = new BigDecimal(
                new BigInteger("12"),
                new MathContext(1, RoundingMode.HALF_UP));

        // BigDecimal(String val)
        this.paramString = new BigDecimal("100");

        System.out.println("paramVal = " + this.paramVal);
        System.out.println("paramValAndScale = " + this.paramValAndScale);
        System.out.println("paramValAndScaleAndMc = " + this.paramValAndScaleAndMc);
        System.out.println("paramValAndMc = " + this.paramValAndMc);
        System.out.println("paramString = " + this.paramString);
    }

    /**
     * abs()
     * Returns a BigDecimal whose value is the absolute value of this BigDecimal, and whose scale is this.scale().
     *
     * add(BigDecimal augend)
     * Returns a BigDecimal whose value is (this + augend), and whose scale is max(this.scale(), augend.scale()).
     *
     * compareTo(BigDecimal val)
     * Compares this BigDecimal with the specified BigDecimal.
     *
     * divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
     * Returns a BigDecimal whose value is (this / divisor), and whose scale is as specified.
     *
     * divideAndRemainder(BigDecimal divisor)
     * Returns a two-element BigDecimal array containing the result of divideToIntegralValue followed by the result of remainder on the two operands.
     *
     * max(BigDecimal val)
     * Returns the maximum of this BigDecimal and val.
     *
     * min(BigDecimal val)
     * Returns the minimum of this BigDecimal and val.
     *
     * pow(int n)
     * Returns a BigDecimal whose value is (thisn), The power is computed exactly, to unlimited precision.
     *
     * setScale(int newScale, RoundingMode roundingMode)
     * Returns a BigDecimal whose scale is the specified value, and whose unscaled value is determined by multiplying or dividing this BigDecimal's unscaled value by the appropriate power of ten to maintain its overall value.
     */
    private void methods(){
        // abs()
        System.out.println("abs() = " + this.paramValAndScale.abs());

        // add(BigDecimal augend)
        System.out.println("add(BigDecimal augend) = " + this.paramVal.add(this.paramValAndScale));

        // compareTo(BigDecimal val)
        System.out.println("compareTo(BigDecimal val) = " + this.paramVal.compareTo(this.paramValAndScale));

        // divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
        System.out.println("divide(BigDecimal divisor, int scale, RoundingMode roundingMode) = " + this.paramVal.divide(new BigDecimal("13"), 3, RoundingMode.HALF_UP));

        // divideAndRemainder(BigDecimal divisor)
        System.out.println("divideAndRemainder(BigDecimal divisor) = " + Arrays.toString(this.paramValAndScaleAndMc.divideAndRemainder(this.paramVal)));

        // max(BigDecimal val)
        System.out.println("max(BigDecimal val) = " + this.paramValAndScaleAndMc.max(this.paramVal));

        // min(BigDecimal val)
        System.out.println("min(BigDecimal val) = " + this.paramValAndScaleAndMc.min(this.paramVal));

        // pow(int n)
        System.out.println("pow(int n) = " + this.paramVal.pow(2));

        // setScale(int newScale, RoundingMode roundingMode)
        System.out.println("setScale(int newScale, RoundingMode roundingMode) = " + this.paramValAndScaleAndMc.setScale(5, RoundingMode.HALF_DOWN));
    }

}

 

 


더 많은 내용을 보시려면 아래를 참고하세요.


https://docs.oracle.com/javase/8/docs/api/

https://madplay.github.io/post/the-need-for-bigdecimal-in-java

 

 

블로그의 다른 글

 

JSP 데이터 전송하는 방법 - form태그 (GET, POST방식 설명)

- form 태그란? 클라이언트에서 서버에게 데이터를 전송할 때 사용하는 HTML의 태그입니다. - 전송방식 전송방식에는 POST, GET 2개의 방식이 있습니다. (1) GET 방식 GET 방식은 클라이언트가 서버에게

developer-syubrofo.tistory.com

 

JSP 자바빈(JavaBean)이란 무엇일까?

- 자바빈(JavaBean)이란? 자바로 작성된 컴포넌트들 즉, 클래스(Class)를 일반적으로 말합니다. JSP 프로그래밍에는 DTO(Data Transfer Object)나 DAO(Data Access Object)클래스의 객체를 JSP페이지에서 사용하..

developer-syubrofo.tistory.com

 

JSP 페이지 구성 요소 - Page directive(페이지 지시어)

<%@page%>, <%@include%>, <%@taglib%>로 3가지가 있습니다. 1. <%@page%>란? 클라이언트의 요청에 의해 실행되는 JSP 페이지의 필요한 정보를 지정합니다.  속성 사용법 기본값 설명 info info = "설명" - 페..

developer-syubrofo.tistory.com

 

JSP 페이지 구성 요소 - 스크립트 요소

- 스크립트 요소란? JSP 페이지에서 자바코드를 사용할 수 있는 영역을 의미합니다. - 스크립트 요소의 종류 선언문(<%! %>), 스크립트릿(<% %>), 표현식(<%= %>) 3가지 입니다. 아래는 스크립트를 사용

developer-syubrofo.tistory.com

 

반응형 페이지 만들 때 css

1. div로 각각의 영역을 지정한다. 2. width는 %로 지정하고, height의 경우 margin, padding으로 지정한다. div로 다른 태그들을 감싸고 있다면 padding과 margin을 추가하기가 수월하다. 3. ul, li 태그의 경우..

developer-syubrofo.tistory.com