자바의 신 11장을 학습하다가 대부분 java docs 사용법? 에 대한 내용이라 어떤 걸 정리해야 할지 몰라
'직접해 봅시다'파트에 BigDecimal API를 열어보라고 하길래 알아보고자 했다.
결제나 큰 숫자 다룰 때 사용한다고 들어서 중요하구나~라고 듣기만 했다.
BigDecimal이란?
java.math 패키지에 속한 클래스로 정밀한 숫자 연산에 사용된다.
주로 금융이나 과학 계산 등에서 부동 소수점 연산의 오차를 방지하고 정확한 결과를 얻고자 할 때 사용된다.
부동 소수점 연산의 오차란?
public class Main {
public static void main(String[] args) {
double a = 0.1;
double b = 0.2;
double sum = a + b;
System.out.println("0.1 + 0.2 = " + sum);
}
}
위 코드의 결과는 0.3이 나올 것 같지만 실제로는 0.300000000000004와 같은 미세한 오차가 발생한다.
이는 double이 소수점 이하를 근사값으로 표현하기 때문이다.
왜 오차가 발생할까?
부동 소수점 연산은 `double`과 `float` 타입을 사용하며, 이는 **IEEE 754 표준**에 따라 숫자를 2진수로 표현한다.
하지만 10진수 소수를 2진수로 변환할 때, 정확히 표현되지 못하는 숫자가 존재한다.
0.1과 0.2가 이진법으로 정확히 표현되지 못하기 때문에 무한 소수로 표현된다.
더욱 확실히 이해하기 위해선 고정소수점, 부동소수점 표현방식을 알아야 한다.
고정소수점, 부동소수점 표현방식이 뭔데..?
이 방식들은 컴퓨터가 실수를 어떻게 저장하고 처리하는지를 이해하는 데 중요한 개념이다.
두 가지의 차이점은 소수를 다루는 방식이다!
고정소수점 표현방식
고정소수점 표현방식은 실수를 부호부, 정수부, 소수부로 나누어 표현하는 방식이다.
자릿수를 고정하여 실수를 표현한다.
실수 7.75을 2진수로 변환해보자.
- 7.75는 2진수로 111.11
- 7 -> 111
- 0.75 -> 0.11
32비트 기준으로 아래와 같이 표현된다.
0(부호) 0000111(정수부) 11000000(소수부)
양수니까 부호는 0이고 각각 정수부, 소수부에 담아 표현한다.
고정 소수점은 소수점의 위치가 고정되어 있기 때문에 쉽게 저장되고 연산도 빠르다는 장점이 있다.
하지만 자릿수가 고정되어 있기 때문에 표현할 수 있는 범위가 제한적이다.
이에 더 넓은 범위의 실수를 표현하기 위해 부동소수점이라는 개념이 등장했다.
부동소수점 표현방식
부동 소수점 방식은 실수를 부호부, 가수부, 지수부로 나누고 숫자를 정규화해서 각 비트에 나눠 담아 표현한다.
정규화(Normalization)라는 것은 숫자를 1.xxxx × 2^n 형태로 표현하는 것이다.
수식으로는 부호 * M(가수부) * 2^E(지수부)_로 표현할 수 있다.
똑같이 7.75를 표현해 보자.
정확한 정규화 과정은 아래와 같다는데 아직 이해를 못 했다..
BigDecimal의 방식
`BigDecimal`은 10진수(Decimal) 기반으로 숫자를 표현한다. 즉, 모든 숫자를 10의 거듭제곱 형태로 저장하여 정확한 수치 계산이 가능하다.
내부적으로 숫자를 정수의 배열 형태로 저장하며, 소수점 위치를 별도로 관리한다.
BigDecimal은 내부적으로 `unscaledValue`, `scale` 이 두 가지 주요 변수로 수를 표현한다.
0.01을 예로 들어보자.
BigDecimal에서 0.01의 표현 방식
0.01은 10진수로 표현하면 1이라는 숫자가 소수점 아래 두 번째 자리에 있는 것이다.
`unscaledValue`의 결정
소수점을 제거한 숫자의 순수 정수 부분이 unscaledValue가 된다.
0.01에서 소수점을 제거하면 `1`이 된다.
따라서 unscaledValue는 `1`이다.
`scale`의 결정
소수점을 오른쪽으로 몇 자리 이동했는지를 나타내는 값이 scale이다.
0.01은 소수점을 오른쪽으로 두 번 이동하면 정수 `1`이 된다.
따라서 scale은 `2`이다.
따라서 아래와 같이 BigDecimal로 0.01을 생성하면
BigDecimal value = new BigDecimal("0.01");
객체의 내부 상태는 다음과 같이 저장된다
- unscaledValue: `1`
- scale: `2`
'💻 Dev > Java' 카테고리의 다른 글
가비지 컬렉터(GC) feat.힙 영역 (0) | 2024.11.23 |
---|---|
자바는 Call by Value만 사용한다. (0) | 2024.11.22 |
String Constant Pool, feat. Runtime Constant Pool (0) | 2024.11.02 |
Immutable(불변성), StringBuffer와 StringBuilder (0) | 2024.10.29 |
자바 코드의 메모리 영역(스택&힙) (0) | 2024.10.29 |
JVM 구조와 동작 과정 (0) | 2024.10.29 |