티스토리 뷰
let sum = 0.1 + 0.2;
console.log(sum); // 0.30000000000000004
0.1과 0.2를 더하면 0.3이 나올 것 같은데 이상하게 콘솔에는 0.3이 아니라 0.3에 가까운 숫자가 출력됩니다.
이런 간단한 더하기조차 못하는 JavaScript가 갑자기 못 미더우신가요?
그런데 이건 자바스크립트만의 문제가 아니라 Python, Ruby, Java 등 대부분의 프로그래밍 언어에서도 똑같이 발생하는 오류입니다. 그럼 이런 단순한 계산도 못하는 경우가 도대체 왜 발생하는 걸까요?
이런 부정확한 숫자 계산의 가장 큰 원인은 사람과 컴퓨터 사이에 숫자를 다루는 방식이 서로 다르기 때문입니다.
컴퓨터의 모든 코드는 0과 1로만 이루어져 있다는 이야기를 들어 보신 적 있으신가요?
실제로도 우리가 작성한 모든 코드들은 어떤 특별한 과정을 거쳐서 0과 1로 이루어진 2진수로 변환된 다음에 컴퓨터가 해석을 하는데요.
우리가 3분의 1이라는 분수를 소수로 표현하려다 보면 0.33333으로 무한소수가 되는 경우가 있죠?
비슷한 원리로 우리가 일반적으로 사용하는 10진수의 소수 표현을 2진수로 바꿔서 계산을 하다 보면 무한소수가 되는 경우가 발생합니다.
그런데 이 무한소수는 말 그대로 숫자가 무한히 이어지기 때문에 딱 명확하게 표현할 수 있는 방법이 없습니다.
그래서 JavaScript가 숫자를 표현할 수 있는 범위 내에서 특정한 자리에서 숫자를 반올림해버리는데요.
여기서 발생하는 미세한 차이가 바로 오차로 발생하는 겁니다.
간단하게 이 문제를 해결하는 방법은 toFixed 메소드를 활용해서 필요한 자릿수에 맞춰서 반올림되게끔 만들어주는건데요. 이렇게 하면 0.3이 잘 출력이 됩니다. 그런데 toFixed 메소드의 결과는 문자열입니다.
그렇기 때문에 숫자로 사용하려면 형 변환을 해야 하기 때문에 Number 함수를 사용하거나 더하기 기호를 앞쪽에 붙여주면서 숫자형으로 만들어주면 됩니다.
let sum = 0.1 + 0.2;
console.log(Number(sum.toFixed(1)));
console.log(+sum.toFixed(1));
그리고 같은 원리로 Math 객체의 round 메소드를 활용하는 방법도 있습니다.
필요한 소수점 자리수만큼의 10의 거듭제곱을 곱해서 먼저 정수로 만들어주고 round 메소드로 계산을 한 다음 다시 그만큼 나눠주는 방식을 활용하는 것입니다.
let sum = 0.1 + 0.2;
console.log(Math.round(sum * 10) / 10);
3분의 1을 명확한 10진수로 완벽하게 다루지 못하듯이 2진수로 변환했을 때 무한소수로 나타나는 계산 오류를 완벽하게 방지하는 방법은 사실상 없습니다. 필요한 상황에 따라 적절한 수로 반올림해야 합니다.
'프론트엔드 > JavaScript' 카테고리의 다른 글
[자료형 심화] 08. 문자열과 배열 사이 (0) | 2022.10.24 |
---|---|
[자료형 심화] 07. 문자열 심화 (0) | 2022.10.24 |
[자료형 심화] 04. Math객체 (0) | 2022.10.24 |
[자료형 심화] 02. 숫자형 메소드 (0) | 2022.10.24 |
[자료형 심화] 01. 다양한 숫자 표기법 (0) | 2022.10.19 |
- Total
- Today
- Yesterday
- 느슨한 타입(loosely typed)
- redux
- undefined
- 기본형 데이터
- 동적(dynamic) 언어
- redux thunk
- 얕은복사
- foreach
- 불변 객체
- 비교 연산자
- redux-middleware
- redux-thunk
- some
- find
- EVERY
- 참조형 데이터
- null
- findindex
- map
- filter
- redux middleware
- 타입변환
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |