자바 뿐만 아니라 모든 컴퓨터 언어에서 소수 계산을 하다보면 문제가 발생하는데 사실 문제 해결하는데 급급했으나
대략적으로만 알고 있지 정확히 설명할 수 없었다.
그래서 이번 기회를 통해 한 번 정리하고자 한다
컴퓨터에서 실수형 표현
- 컴퓨터 데이터는 전기신호에 기반한 비트(2진수)
- 하지만 정수와 다르게 실수형에서 소수의 표현은 이진수로 표현의 한계가 발생한다
- 예를들어 3.141592… 같은 숫자의 표현은 무한소수
- 0.1을 이진수로 표현해도 무한소수이다
- 근데 근사값으로도 충분하다고 판단하여 고정 소수점과 부동 소수점을 사용한다
고정 소수점
- 1비트의 부호 비트와 15비트의 정수부, 16비트의 소수부로 구성되어 있다
- 하지만 표현할 수 있는 수의 한계가 명확하다
부동 소수점
- 표현할 수 있는 값을 최대한 넓혀 오차를 줄이기 위함
- 메모리에 지수부(8bit), 가수부(23bit)로 나눈다
- 가수부에는 실제 데이터 비트가 들어가고, 지수부에 소수점 위치를 가리키는 제곱승이 들어간다

자바에서 소수의 표현
- IEEE754에 따른다
- float, 단일 정확도(32bit): (부호부 1 비트, 지수부 8 비트, 가수부 23비트)
- double, 이중 정확도(64bit) : (부호부 1 비트, 지수부 11 비트, 가수부 52 비트)
프로그래밍 소수의 계산
- 아무리 부동 소수점이라도 무한 소수의 표현의 한계가 발생한다
- 어느정도 끊어서 반올림 해줘야하는데 계산 할 때 부정확한 결과를 가져온다
public class Main {
public static void main(String[] args) {
double val1 = 12.23;
double val2 = 34.45;
System.out.println(val1 + val2);
}
}
// 46.68000000000001
자바만 그럴까?

- 자바스크립트로 동일하게 테스트했을 때 같은 결과가 나온다
- 어떤 언어에서든지 동일한 문제가 발생한다
해결방법1. 정수로 치환
public class Main {
public static void main(String[] args) {
double val1 = 12.23 ;
double val2 = 34.45;
int value = (int)((val1 * 100) + (val2 * 100));
System.out.println((double)value / 100) ;
}
}
- 소수 자리수가 적거나 고정되어있을 경우는 가능할 것으로 판단된다
- 허나 코드 가독성 부분에서 불편하다
해결방법2. BigDecimal 클래스
public class Main {
public static void main(String[] args) {
BigDecimal val1 = new BigDecimal("12.23");
BigDecimal val2 = new BigDecimal("34.45");
System.out.println(val1.add(val2));
}
}
참고 사이트
https://inpa.tistory.com/entry/JAVA-☕-실수-표현부동-소수점-원리-한눈에-이해하기
'BackEnd > JAVA' 카테고리의 다른 글
| [자바 JVM 모니터링]VisualVM을 통한 모니터링 해보기 (0) | 2024.10.30 |
|---|---|
| [용어정리] JCP, JSR, JSR-310 정리 (0) | 2024.10.16 |
| 해싱과 자바의 hashcode에 관하여 (0) | 2024.10.04 |
| 스트림 이용한 범위 내 카운트 (1) | 2023.03.12 |
| 배열 역순으로 정렬하기 (0) | 2023.03.10 |