Number 오브젝트
JS는 IEEE 754에 정의된 64비트 부동 소수점으로 수를 처리한다.
1) 부동 소수점
컴퓨터에서 실수를 표현하는 방식 중 하나다. 소수점 이하의 숫자를 '이진법'(컴퓨터는 0과 1로 이루어져 있으니)으로 표현하며 소수점의 위치와 지수를 사용해 값을 나타낸다. 예컨대 십진법에서의 0.1은 이진법으로 정확히 표현할 수 없다. 0.1을 이진법으로 변환하면 무한 소수가 되기 때문에 부동소수점은 이러한 수를 근삿값으로 표시한다. IEEE 754 표준은 가장 널리 사용되는 부동소수점 표현 방식으로, 64 비트 또는 32비트 형식으로 저장되는데 JS의 Number 데이터 타입은 64비트 형식을 사용한다.
2) 64비트를 사용한다는 건
숫자 1을 처리하든 1억을 처리하든 수를 처리할 때 JS는 무조건 64비트를 사용한다. 0을 사용할 때도 64비트를 사용하는 건 효율이 떨어지지 않냐는 측면을 갖고 있지만, ES6+ TypedArray는 사용자가 사용할 비트 수를 정의할 수 있어 메모리 효율 부분을 보완할 수도 있다.
3) 정수와 실수를 구분하지 않는다.
1을 1.0으로 처리한다. 1과 1.2를 더할 수도 있다. 이렇게 정수와 실수를 더할 수 있는데, 정수는 정수끼리 실수는 실수끼리만 계산할 수 있는 언어들도 있다. 어떤 언어가 더 좋고 나쁘다라고 말할 수는 없지만, 정수와 정수끼리만 더하는 언어의 경우 메모리를 사용하는 바이트 수를 줄일 수 있어서 조금 더 효율적이긴 한다.
64비트
- 사인비트: 63비트, 1비트를 차지한다. 이 값이 0이면 양수고, 1이면 음수를 나타낸다.
- 지수: 52~62비트, 11비트를 차지한다. 숫자의 크기를 표현하는 지수 값을 저장한다.
- 가수: 0~52비트, 52비트를 차지한다. 우리가 이야기 하는 일반적인 숫자며 사인 비트를 포함해 총 53비트를 차지한다.
비트 값은 0 아니면 1로 그 값은 2^자릿수로 값을 구한다.
예를 들어 1, 1, 1이라면 가수의 0비트부터 1비트, 2비트까지 구하는데 2^0+2^1+2^2= 7이 나온다.
Number 상수
safe integer란 지수(e)를 사용하지 않고 나타낼 수 있는 값을 말한다.
가수 부분이 safe integer로 사인 부분만 추가한 형태다.
safe integer는 최댓값과 최솟값이 존재한다.
2^53은 safe integer 범위에 해당하지 않는 '안전하지 않은 정수'다.
안전하지 않은 정수란 위에서 말한 부동소수점으로 처리되어 정확성을 보장할 수 없다.
Epsilon
부동소수점에서 허용되는 상대적인 오차의 한계로 아주 아주 작은 값이다.
2.2204460492503130808472633361816E-16 또는 2^-52의 값을 갖는다.
아주 미세한 값의 차이 형태, 이를 같은 값으로 간주할 때 사용된다.
그 유명한 0.1+0.2 !== 0.3이 여기서 나온다.
위에서 말했지만 0.1을 이진법으로 변환하면 무한소수가 되기 때문에 부동소수점은 이를 근삿값으로 표시한다.
Number.isSafeInteger(0.1) === false가 나오는 부분에서 0.1은 안전하지 않은 정수라는 것을 확인할 수 있다.
즉 0.1은 실제로 0.1이 아니라 2진법으로 표현하면 아래와 같이 생겼다.
이러한 수를 JS는 그대로 표현할 수가 없어 가장 가까운 근삿값으로 반올림하는데, 그렇기 때문에 정확한 십진수 표현과는 약간의 차이가 생긴다. 이 부분이 위에서 말한 부동 소수점 연산의 부작용이다. 이를 해소하기 위해서는 Decimal.js 같은 라이브러리를 쓰거나 toFixed()같은 메서드를 사용하면 된다.
아무튼 앱실론으로 다시 돌아가서 매우 매우 작은 값이라는 것이다.
const value = Math.abs(0.1 + 0.2 - 0.3);
console.log(value < Number.EPSILON) // true
또 0/0의 값도 방지할 수 있다.
console.log(0 / 0) //NaN
const value = 0 / (0 + Number.EPSILON)
console.log(value) // 0
진수
2진수
- 숫자 0 다음에 b/B를 작성하고 이어서 0/1을 작성하는 형태
const value = 0B111
console.log(value) // 7 (1+2+4)
8진수
- 숫자 0 다음에 o/O을 작성하고 이어서 0~7을 작성한다.
const value = 0O111;
console.log(value) // 73 (1+8+64)
Number 함수
isNaN()
- NaN 값의 여부를 체크해서, NaN 값이면 true / 아니면 false를 반환한다.
- NaN !== NaN (NaN은 자기 자신과도 일치하지 않는 특별한 값이다.)
- 글로벌 오브젝트에서 isNaN는 값 타입이 Number가 아닌, 말 그대로 NaN를 체크한다.
- Number.isNaN에서는 값 자체가 NaN인 것을 체크한다.
console.log(Number.isNaN("ABC"), isNaN("DEF")) // false, true
console.log(Number.isNaN(NaN), isNaN(NaN)) // true, true
console.log(Number.isNaN(0/0), isNaN(0/0)) // true, true
console.log(Number.isNaN("100"), isNaN("200")) // false, false
isInteger()
- 값이 정수면 true / 아니면 false를 반환한다.
- 별도로 문자형이나 불리언 값을 숫자형으로 변환하지 않는다.
console.log(Number.isInteger(0)) // true
console.log(Number.isInteger(1.0)) // true
console.log(Number.isInteger(1.01)) // false (소수)
console.log(Number.isInteger("12")) // false (문자형 -> 숫자형으로 변환하지 않음)
console.log(Number.isInteger(true)) // false
isSafeInteger()
- 안전한 정수라면 true / 아니면 false를 반환한다.
- 안전한 정수의 범위는 -2^53-1 ~ 2^53-1 까지다.
const isSafe = Number.isSafeInteger;
console.log(isSafe(7.0)) // true
console.log(isSafe(Number.MAX_SAFE_INTEGER)) // true
console.log(isSafe(Number.MIN_SAFE_INTEGER)) // true
const isSafe = Number.isSafeInteger;
console.log(7.1)) // false
console.log("100")) // false
console.log(NaN)) // false
console.log(infinity)) // false
isFinite()
- 유한한 값이면 true / 아니면 false를 반환한다.
- 글로벌 오브젝트의 isfinite()와 값이 다르다.
const num = Number.isFinite;
const global = isFinite;
console.log(num(100), global(200)) // true, true
console.log(num("70"), global("80")) // false, true
console.log(num(true), global(true)) // flase, true
console.log(num(NaN), global(NaN)) // false, false
console.log(num(undefined), global(undefined)) // false, false
Number로 true를 표현하면 1이 나온다.
글로벌 오브젝트에서는 Number형으로 문자형이든 불리언이든 변환해주지만 Number형은 그렇지 않다.
그것도 그런게 num에서 isFinite면 숫자와 관련된 것에서 사용할 목적이라 생각하면 된다.
'👋🏻 JavaScript > 📖 자바스크립트 ES6+' 카테고리의 다른 글
[JS] String 오브젝트 중 다양한 메서드를 알아보자 (0) | 2023.06.20 |
---|---|
[JS] String 오브젝트 중 유니코드(Unicode)를 알아보자 (0) | 2023.06.20 |
[JS] getter, setter를 알아보자 (0) | 2023.06.15 |
[JS] Default Value를 알아보자 (0) | 2023.06.15 |
[JS] 구조 분해 할당을 알아보자2 (0) | 2023.06.15 |