김 양의 멋따라 개발따기
2.0 + 4.4 + 6.2 + 2.4 = 15.000000000000002 이 되는 자바스크립트의 부동소수점 오차 본문
1. 왜 2.0 + 4.4 + 6.2 + 2.4 이 15.000000000000002가 될까?
자바스크립트에서 숫자는 대부분 IEEE 754 64-bit 부동소수점 형식으로 저장돼요.
쉽게 말하면:
- 고정된 64개의 비트 안에
- 부호(sign) 1비트
- 지수(exponent) 11비트
- 가수(fraction, mantissa) 52비트
이렇게 나눠서 **“2진수 실수”**를 표현합니다.
문제는 우리가 사용하는 10진수 소수가
**2진수로 “딱 떨어지지 않는 경우가 많다”**는 겁니다.
예를 들어:
- 1/10 (0.1)
- 2/10 (0.2)
- 4.4, 6.2, 2.4 …
이런 수들은 2진수로 표현하면 무한히 반복되는 소수가 됩니다.
10진수에서 1/3 = 0.33333... 끝없이 반복되는 것처럼요.
컴퓨터는 52비트까지만 저장할 수 있으니
중간에 잘라서(반올림해서) 저장할 수밖에 없습니다.
그래서 실제로는:
- 4.4 → 내부적으로는 4.400000000000000355... 비슷한 값
- 6.2 → 6.200000000000000177... 비슷한 값
이런 식의 아주 살짝 틀어진 값으로 저장됩니다.
2. “콘솔에는 4.4로 보이는데?” → 출력할 때 깎아서 보여줘서 그래요
console.log(4.4)를 찍으면 브라우저는
사람이 보기 좋게 적당한 자리까지만 문자열로 만들어 보여줍니다.
실제 내부 값은 4.400000000000000355...인데
보여줄 때는 4.4로 반올림해서 출력하는 거예요.
하지만 덧셈을 하면 진짜 저장된 값끼리 계산하기 때문에
오차가 눈에 보이는 숫자로 튀어나오는 거죠 → 15.000000000000002
3. 부동소수점의 핵심 개념 정리
- 2진수 기반 실수 표현
- 컴퓨터는 2진수만 다룰 수 있어서
실수도 “2진수 소수”로 표현해야 함.
- 컴퓨터는 2진수만 다룰 수 있어서
- 표현 가능한 숫자가 한정됨
- 64비트 안에서만 표현해야 하므로
대부분의 10진수 소수는 근사값으로 저장됨.
- 64비트 안에서만 표현해야 하므로
- 근사값의 합 = 또 다른 근사값
- 오차들이 더해지고 빼이다 보면
어느 순간 0.30000000000000004, 15.000000000000002 같은 결과 등장.
- 오차들이 더해지고 빼이다 보면
- 자바스크립트, 파이썬, 자바, C 등 거의 모든 언어가
기본 실수 타입으로 같은 방식을 씀(IEEE 754).
4. 그래서 실무에서 어떻게 처리하나?
1) 표시할 때 반올림해서 보여주기 (UI용)
점수처럼 소수점 한 자리까지면 충분한 경우:
const sum = Number(value1) + Number(value2) + Number(value3) + Number(value4);
// 소수 1자리까지 반올림해서 숫자로
const rounded = Math.round(sum * 10) / 10;
sumTd.innerText = rounded;
// 항상 한 자리까지 문자열로 보여주고 싶으면
sumTd.innerText = rounded.toFixed(1); // "15.0"
2) 정수로 바꿔서 계산하기 (고정소수점 느낌)
예를 들어 점수가 항상 “소수 첫째 자리까지”라면
10을 곱해서 정수로 계산하는 방법도 자주 써요.
function toInt10(v) {
return Math.round(Number(v) * 10); // 예: 4.4 -> 44
}
const sum10 =
toInt10(value1) +
toInt10(value2) +
toInt10(value3) +
toInt10(value4);
const sum = sum10 / 10; // 다시 10으로 나누기
sumTd.innerText = sum.toFixed(1); // "15.0"
이렇게 하면 내부적으로는 정수 덧셈이라
부동소수점 오차가 훨씬 줄어듭니다.
'TIL' 카테고리의 다른 글
| JavaScript !! (느낌표 두 개) 완전 정리: 왜 쓰고, 언제 위험할까? (0) | 2026.01.19 |
|---|---|
| 변수 선언하지 않고 JS에서 HTML 요소 사용할 수 있다? (0) | 2025.09.26 |
| JavaScript - Pinch Zoom 보완하기 (4) | 2025.07.24 |
| 집에 가고 싶을 때 퇴근 타이머 만들기 (2) | 2025.07.11 |
| Index DB 사용해보기 (2) | 2025.06.19 |