Search
📏

부동소수점 오차 : 0.1 계산 문제

날짜
2025/03/12
태그
스터디
공부
프로젝트
SSAFY
공개여부

0.1 + 0.1 + 0.1 ≠ 0.3

python, java, javaScript 등의 프로그래밍 언어에서 0.1 을 단순히 3번 덧셈하는 연산을 하게 되면, 0.3이 결과로 나오지 않고 뒤에 이상한 소수점이 나오는 것을 볼 수 있다.
이렇게 나오는 이유는 컴퓨터가 2진법으로 소수를 다루다보니 생기는 문제이다.
python 에서 계산오차
javaScript 에서 계산오차
java 에서 계산오차

2진법에서 소수 표현하기

2진법에서 실수를 표현하는데 소수를 사용한다. 실수를 32비트로 표현할 때 부호비트 1칸 + 지수부분 8칸 + 가수부분 23칸 으로 표현하게 된다. 가수 부분에는 정수부분을 2진법으로 나타낸 결과가 들어가고, 지수 부분에는 소수부분을 2진법으로 나타낸 결과가 들어간다.
정수 부분을 계산할 때는 2로 나누어가며 계산해주고, 실수 부분을 계산할 때는 2로 곱해가며 계산해준다.

2진법으로 실수 표현하기

예를 들어 5.125를 2진법으로 나타내면, 정수 부분 5, 실수부분 0.125 로 분리해준다.
정수 부분
5 / 2 = 2 나머지 1 2 / 2 = 1 나머지 0 1 / 2 = 0 나머지 1 -> 5 = 101 (2)
Plain Text
복사
정수 부분인 5를 표현하면 101이 된다.
소수 부분
0.125 * 2 = 0.25 -> 0 기록 | 0.25남음 0.25 * 2 = 0.5 -> 0 기록 | 0.5남음 0.5 * 2 = 1 -> 1 기록 | 0.0 남음
Plain Text
복사
소수 부분인 0.125를 표현하면 0.001 이다.
최종적으로 결합하면 101.001이 된다.

2진법으로 0.1 표현하기

같은 방식으로 0.1을 표현하게되면 무한히 끝나지 않는 결과를 볼 수 있다.
0.1 × 2 = 0.2 → 0 기록, 0.2 남음 0.2 × 2 = 0.4 → 0 기록, 0.4 남음 0.4 × 2 = 0.8 → 0 기록, 0.8 남음 0.8 × 2 = 1.6 → 1 기록, 0.6 남음 0.6 × 2 = 1.2 → 1 기록, 0.2 남음 0.2 × 2 = 0.4 → 0 기록, 0.4 남음 ...
Plain Text
복사
0.1을 2진법으로 표현하게 되면 0.001100110011… 과 같이 무한소수가 된다. 컴퓨터에서는 제한된 비트 수로 무한 소수를 표현해야 하므로 이를 잘라서 근사치를 보관하게 된다.

해결방법

BigDecimal

자바에서 BigDecimal 을 사용하여 10진법 실수 계산을 할 수 있다. 인자로 실수를 전달할 때 문자열 형태로 전달해야한다.
BigDecimal a = new BigDecimal("0.1"); BigDecimal result = a.add(a).add(a); // 0.1 + 0.1 + 0.1 System.out.println(result); // 0.3 출력 System.out.println(result.equals(new BigDecimal("0.3"))); // true 출력
Java
복사

정수로 변환하기

실수의 소수 부분이 없어지도록 10n10^n 을 곱하여 계산 후 계산결과를 다시 10n10^n으로 나눠주면 된다.
// 달러 대신 센트로 계산 double dollar = 0.1; double cent = dollar * 100;// 0.1 달러 = 10 센트 double result = cent + cent + cent; // 30 센트 double finalResult = result / 100; // 다시 달러로 변환 System.out.println(finalResult); // 0.3
Java
복사