JAVA

Java에서 큰 수를 다룰 때 쓰는 자료형이란? (BigDecimal 에 관해)

쿠카이든 2024. 4. 6. 23:14
728x90
BigDecimal을 쓰는 이유
Test

자바는 IEEE 754 부동 소수점 방식을 사용해서,
정확한 실수를 저장하지 않고 최대한 완벽에 가깝기를 바라는 근사치 값을 저장하기 때문에 통과하지 못한다.

금융권에서 달러를 다루는 개발자가 double을 이용해서 이런 사소한 값 차이가 발생한다면 부동 소숫점 방식이 아닌, 정수를 이용해 실수를 표현하는 java.math.BigDecimal 클래스를 사용해야 한다.

따라서, Java 언어에서 돈과 소수점을 다룬다면 BigDecimal은 선택이 아니라 필수다.

변수
  • intValue : 정수. 정수를 저장하는데 BigInteger를 사용한다.
  • scale : 지수. 정확히는 소수점 첫째 자리부터 0이 아닌 수로 끝나는 위치까지의 총 소수점 자리수이다.
  • precision : 정밀도. 정확히는 0이 아닌 수가 시작하는 위치부터 오른쪽부터 0이 아닌 수로 끝나는 위치까지의 총 자리수이다.
    아래 출력 결과로 각 변수의 의미를 파악하자.
BigDecimal의 생성

BigDecimal의 생성 방법은 여러가지가 있는데,
문자열로 숫자를 표현하는 것이 일반적이다.
기본형 리터럴로는 표현할 수 있는 값의 한계가 있는데, 예를 들어
double 타입의 값을 그대로 전달할 경우
앞서 사칙연산 결과에서 본 것과 같이 예상과 다른 값을 얻을 수도 있다.

BigDecimal val;
val = new BigDecimal("12345.6789");
val = new BigDecimal(12345.678); // 오차가 날 수 있음
val = new BigDecimal(12345);
val = BigDecimal.valueOf(12345.67); // 오차가 날 수 있음
val = BigDecimal.valueOf(123456);

728x90
BigDecimal의 비교

BigDecimal은 Comparable<BigDecimal>를 구현하고 있기 때문에,
equals()를 통해 내용을 비교할 수 있다.
여기서 주의할 점은 12.01과 12.010은 같지 않다.

BigDecimal의 타입 변환
문자열로 변환
String toPlainString(); // 무조건 다른 기호 없이 숫자로만 표현
String toString(); // 필요시 지수 형태로 표현할 수도 있음

 Number를 상속받고 있기 때문에 Number의 기본형으로 변환하는 메서드를 가지고 있다.

int intValue()
long longValue()
float floatValue()
double doubleValue()

또 BigDecimal을 정수형으로 변환하는 메서드 중,
이름 끝에 Exact가 붙은 것은 변환 결과가 변환 타입 범위에 속하지 않으면
ArithmeticException을 발생시킨다.

테스트 성공 !

BigDecimal의 연산

먼저 기본적인 연산을 수행하는 메서드들이다.

BigDecimal add(BigDecimal val)
BigDecimal subtract(BigDecimal val)
BigDecimal multiply(BigDecimal val)
BigDecimal divide(BigDecimal val)
BigDecimal remainder(BigDecimal val)

테스트 성공 !

참고로 BigDecimal은 불변 객체이기 때문에
연산 후 반환 타입이 BigDecimal인 경우 새로운 인스턴스가 반환된다.

추가로 다른 연산과 달리 divide()은 메서드가 다양한 버전으로 오버로딩 되어있다.
어떻게 반올림할지(roundingMode), 몇 번째 자리(scale)에서 반올림 할건지를 지정할 수 있다.

roundingMode

반올림 처리 방법에 대한 것으로 BigDecimal에 정의된 다음 상수들에서 하나를 선택해 사용하면 된다.

  • CEILING – 올림
  • FLOOR – 내림
  • UP – 양수일 경우 올림, 음수일 경우 내림
  • DOWN – 양수일 경우 내림, 음수일 경우 올림
  • HALF_UP – 반올림(5이상 올림, 5미만 버림)
  • HALF_EVEN – 반올림(반올림 자리의 값이 짝수면 HALF_DOWN, 홀수면 HALF_UP)
  • HALF_DOWN – 반올림(6이상 올림, 6미만 버림)
  • UNNECESSARY – 나눗셈 결과가 딱 떨어지지 않으면,ArithmeticException 발생
scale 변경

소수점 위치를 바꾸고 싶을 때는 BigDecimal을 10으로 곱하거나 나누는 것이 아니라,
setScale()을 통해 scale 값을 변경한다.

BigDecimal setScale(int newScale)
BigDecimal setScale(int newScale, int roundingMode)
BigDecimal setScale(int newScale, RounfingMode mode)

주의할 점은 setScale()로 scale을 줄이는 것은 10의 n제곱으로 나누는 것과 같으므로
오차가 발생할 수 있으니 roundingMode를 지정하는 것이 좋다.

참고 : https://velog.io/@new_wisdom/Java-BigDecimal%EA%B3%BC-%ED%95%A8%EA%BB%98%ED%95%98%EB%8A%94-%EC%95%84%EB%A7%88%EC%B0%8C%EC%9D%98-%EB%84%88%EB%93%9C%EC%A7%93

 

[Java] BigDecimal에 관한 고찰 🕵️‍♀️

[Java] 나한테 딱 걸린 BigDecimal 👀

velog.io

https://jsonobject.tistory.com/466

 

Java, BigDecimal 사용법 정리

BigDecimal? BigDecimal은 Java 언어에서 숫자를 정밀하게 저장하고 표현할 수 있는 유일한 방법이다.소수점을 저장할 수 있는 가장 크기가 큰 타입인 double은 소수점의 정밀도에 있어 한계가 있어 값이

jsonobject.tistory.com

https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html

 

BigDecimal (Java Platform SE 8 )

Returns a string representation of this BigDecimal, using engineering notation if an exponent is needed. Returns a string that represents the BigDecimal as described in the toString() method, except that if exponential notation is used, the power of ten is

docs.oracle.com

 

728x90