Java

[Java] BigDecimal - Java에서 정밀한 숫자 표현하기

디벨로펄 2022. 8. 24.
반응형

문제점 : Java 언어에서는 숫자를 표현하기 위해 int, long, double, float 등의 기본형을 사용한다.

이러한 기본형 중에 가장 많이 사용 되는 float, double형은 우리가 원하지 않는 결과를 보여주기도 한다.

double a = 10.0000001;
double b = 7.00010000;
System.out.println(a + b);

--> 결과 : 17.000100099999997

double과 float의 특징

 이진 부동 소수점 연산에 사용되며, 넓은 범위의 수를 빠르게 정밀한 근사치를 구할 수 있도록 설계 되었다.

그 말인 즉, 정밀한 계산과는 맞지 않는다. 이는 이진수를 통해서 0.1과 10의 음의 거듭제곱수를 표현할 수 없기 때문에 발생한다.

10진수로 0.1은 2진수로 표현하면 0.00011001100...과 같은 순환 소수이다.

 

 

■ BigDecimal이란?

실수형을 확장시켜주는 클래스이다. 정밀한 계산에 사용되는 type이며, 이는 double이나 float의 부정확성을 보완하면서 사용할 수 있다.

BigDecimal ba = new BigDecimal("10.0000001");
BigDecimal bb = new BigDecimal("7.00010000");
System.out.println("BigDecimal : " + ba.add(bb));

BigDecimal : 17.00010010

정확한 결과를 도출한 것을 확인할 수 있다.

 

BigDecimal의 원리

내부적으로 배열을 사용해 수치 데이터를 분리해 저장한다.

정수 = in[]

실수 = char[]

BigDecimal의 사용법

정확한 수 표현을 위해 생성자에 문자열을 입력한다.

BigDecimal ba = new BigDecimal("10.0000001"); // 10.0000001 생성

더하기, 빼기, 곱하기, 나누기 등의 연산은 method를 통해 실행된다.

System.out.println("더하기 : " + ba.add(bb)); // 더하기
System.out.println("빼기 : " + ba.subtract(bb)); // 빼기
System.out.println("나누기 : " + ba.divide(bb)); // 나누기 -> 나누어 떨어지지 않으면 error
System.out.println("곱하기 : " + ba.multiply(bb)); // 곱하기

 장단점

- 장점 : 정밀하다.

- 단점

    1) 더 느리다.

    2) 쓰기가 불편하다.

 

★ Insight

정밀한 계산을 위해서는 BigDecimal 사용!

 

빠르고 정밀한 계산을 위해서는?

→ 직접 int, long을 베이스로 한 함수형을 만들면 빠르면서 정확하게 계산 가능

 

실제 활용 사례

a+b+c=1

d+e+f=1

...

 

(a+b+c) *(d+e+f)*(g+h+i) ... =??

회사 업무 중에서 위와 같은 로직에서 결과 값이 0에 가까운 수로 나오는 이슈를 발견했었다.

이때, 임의로 소숫점 6자리까지 반올림을 하고 합이 1이 되지 않는경우, 1보다 큰 경우에 대해서

모자라는 수 만큼을 더하거나 빼서 값을 맞춰주어 해결했었다.

 

 

개발 시작 시점에서는 정밀한 계산에 대한 요구사항이 없었다. 하지만, 시스템이 확장되어가고 기능이 다양해짐에 따라서 정밀함이 요구되었고, 나름의 방법(실제 활용사례)을 통해 해결했었다.

당시에는 BigDecimal에 대해 몰랐고 찾아보지 않았었는데, 최근들어서 누군가는 만들어 뒀을 것 같아서 찾아보니 발견했다.

 

바퀴를 만들지말라!

있을 법한 것이면 검색해서 다른 사람이 만들어 둔 좋은 라이브러리를 가져다 쓸 수 있도록 하자. ㅎ.ㅎ

 

반응형

댓글