https://judahhh.tistory.com/21
내가 정리한 이 글을 보고 내가 정리했지만 그 와중에 몰랐던 것을 발견하여 정리해보려고 한다
숫자 타입에 대해 정확히 알지 못하고 정리한 것 같아 부끄럽다!@!!!
자바스크립트의 데이터 타입 중 숫자 타입에 대해서 알아보자
자바스크립트의 숫자 타입
자바스크립트는 독특하게도 숫자 타입이 하나 밖에 없다. int, long, float, double과 같은 다양한 숫자 타입을 설정하지 않고
단 하나의 숫자 타입만 존재한다. 하나의 숫자 타입만 존재하는데, 실수, 정수 이런 것들을 어떻게 처리하느냐?
자바스크립트의 숫자 타입은 정수만을 위한 타입이 없고 모두 실수로 처리한다. 즉, 정수로 표시되었고 정수인 것 처럼 보이지만
이는 실제로 실수라는 것이다.
console.log(1 === 1.0); //true
//정수로 표시되는 수끼리 나누더라도 실수가 나올 수 있다.
console.log(3/2); //1.5
ECMAScript 사양에 따르면, 숫자 타입의 값은 배정밀도 64비트 부동소수점 형식을 따르며, 즉 모든 실수를 실수로 처리한다. 정수만 표현하기 위한 데이터 타입이 별도로 존재하지 않는다.
64비트 부동소수점
숫자 타입에 대해서 공부하다가 64비트 부동소수점이 정확히 무엇인지 궁금했다. 예시를 통해 알아보자.
우리가 0.1과 0.2를 더하는 연산을 하는 경우, 상식적으로 0.3의 결과값이 나올 것이라고 예상한다.
let result = 0.1 + 0.2;
console.log(result);//0.30000000000000004
하지만 결과는 0.3이 아닌 다른 값이 나온다.
이는 자바스크립트가 숫자타입을 64비트 부동소수점으로 저장하기 때문이라고 한다.
컴퓨터는 모든 데이터를 2진법으로 저장한다. 만약 소수의 경우 분모의 해당하는 수가 2의 거듭제곱 형태이면 유한 소수가 되고
2의 거듭제곱의 형태가 아니면 무한 소수가 된다.
0.1 = 1/10 //분모의 해당하는 수가 10
0.2 = 1/5 //분모의 해당하는 수가 5
//컴퓨터가 2진법으로 0.1과 0.2를 저장하는 경우 이들은 무한소수 형태가 된다.
console.log((0.1).toString(2));
//0.0001100110011001100110011001100110011001100110011001101
//0.1을 2진수로 표현 (64비트 부동소수점으로 저장되어 64비트를 초과하는 부분은 반올림해서 저장)
console.log((0.2).toString(2));
//0.001100110011001100110011001100110011001100110011001101
//0.2를 2진수로 표현 (64비트 부동소수점으로 저장되어 64비트를 초과하는 부분은 반올림해서 저장)
따라서 분모가 무한 소수 형태인 경우 64비트의 공간을 초과하게 된다. 이때 자바스크립트는 64비트를 초과하는 부분을 반올림해서
저장하기 때문에 우리가 원하는 정확한 숫자가 아닌 근사치를 얻게 되는 것이다!
이 과정에서 우리가 기대한 결과 값이 나오지 않는 이유이다.
0.1과 0.2는 무한소수이며 이 둘의 합은 당연히 무한소수이다. 64비트를 초과하므로 근사치로 저장되기 때문에 연산의 오차가 발생한다.
이러한 연산의 오차를 해결하기 위해 자바스크립트에서 외부 라이브러리를 사용해야 한다. ex) BigNumber.js, Big.js, Decimal.js
사실상 실무에서는 위와 같은 연산 오류가 흔하게 발생하지는 않는다고 한다. 하지만 자바스크립트는 숫자를 64비트 부동소수점으로 저장하고 있으며, 언제든지 위와 같은 사례의 오류가 발생할 수 있음을 인지하고 있어야 한다.
참고자료
https://unpasoadelante.tistory.com/23