0.1 + 0.2가 0.3이 아니라고?
"0.1 + 0.2가 0.3이 아니라고?" 프론트엔드 개발을 하다 보면 한 번쯤은 마주하게 되는 순간입니다. JavaScript의 부동소수점 연산 이슈의 원인과 실무에서 활용할 수 있는 해결책들에 대해 정리해두어 같은 이슈를 만났을 때 당황하지 않고 해결하고자 합니다.
문제의 발견
console.log(0.1 + 0.2 === 0.3); // false
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 + 0.3); // 0.6000000000000001
console.log(0.1 * 3); // 0.30000000000000004
console.log(0.3 - 0.1); // 0.19999999999999998
JavaScript가 수학을 못한다고 생각할 수 있지만, 결론부터 이야기하면 컴퓨터 연산의 근본적인 한계 때문입니다.
JavaScript 64비트 숫자의 한계(부동소수점과 고정소수점)
1. 이진법 표현의 한계
컴퓨터는 모든 것을 이진법으로 처리합니다. 십진법에서 간단한 0.1도 이진법으로는 무한소수가 됩니다. 0.1 (십진법) = 0.0001100110011001100... (이진법)
JavaScript는 IEEE 754 표준에 따라 64비트로 숫자를 저장하는데, 무한소수를 유한한 비트로 표현하다 보니 반올림 오차가 발생합니다.
2. 부동소수점 구조
64비트 부동소수점은 다음과 같이 구성됩니다:
부호 비트: 1비트 (양수/음수)
지수 비트: 11비트 (범위 결정)
가수 비트: 52비트 (정밀도 결정)
모든 십진수를 정확히 표현할 수는 없습니다.(Number.MAX_SAFE_INTEGER는 16자리, 15자리는 안전)
실무에서 마주하는 상황들
1. 가격 계산
const price = 19.90;
const tax = 0.08;
const total = price * (1 + tax);
console.log(total); // 21.491999999999997
console.log(`총 가격: $${total.toFixed(2)}`); // $21.49
2. 좌표 계산
let position = 0;
const increment = 0.1;
for (let i = 0; i < 10; i++) {
position += increment;
}
console.log(position); // 0.9999999999999999 (예상: 1.0)
3. 금융 계산
const principal = 1000;
const rate = 0.05;
const time = 12;
const interest = principal * rate * time;
console.log(interest); // 599.9999999999999
해결방법?
소수점 자리 제한
const a = 0.1; const b = 0.2; console.log((a + b).toFixed(1)); // "0.3"
정수 변환
const a = 0.1; const b = 0.2; const multiplier = Math.pow(10, 1); const sum = (a * multiplier) + (b * multiplier); // 3 console.log(sum / multiplier); // 0.3
라이브러리 사용(big.js, decimal.js 등)
배열 기반 십진수 표현
const Big = require('big.js'); const a = new Big(0.1); const b = new Big(0.2); const sum = a.plus(b); console.log(sum.toString()); // "0.3"
const Decimal = require('decimal.js'); const a = new Decimal(0.1); const b = new Decimal(0.2); const sum = a.plus(b); console.log(sum.toString()); // "0.3"
자바스크립트만 그럴까?
부동소수점 이슈는 JavaScript만의 버그가 아니라 근본적인 특성입니다. Java와 같은 언어들도 같은 상황에서의 문제가 발생하고 있는데요. 중요한 것은 이 한계와 쓰임을 알고 적절한 해결책을 선택하는 것 같습니다.
참고
Last updated