[JavaScript] Number

참고 문서

Standard built-in Objects: Number

개요

표준 내장 객체 Number의 필드/메서드 설명 글.

Number() 생성자 함수

new Number()는 주어진 값을 숫자로 변환한다. 주어진 값이 underfined이거나 수가 아닌 문자, 길이가 2 이상인 배열일 때 NaN을 반환한다.

이 생성자 함수의 반환 타입은 레퍼 객체인데, new를 생략하고 일반 함수 Number()로 호출하면 원시 타입의 값을 반환한다. 다만 이 둘의 변환 방식은 같다.

스태틱 프로퍼티

Number.EPSILON

2.220446049250313e-16 값을 반환하는 상수. (소수점으로 표현하면 2.220446049250313 / 10^16 = 0.0000000000000002220446049250313)

자바스크립트는 ECMAScript 표준에 따라 자바스크립트의 모든 산술을 IEEE 754 배정밀도 부동소수점 연산(Double-precision floating-point arithmetic, 64비트)을 사용하여 수행하는데, Number.EPSILON은 이 연산에서 1과 1보다 큰 다음 표현 가능한 숫자 사이의 가장 작은 차이를, 쉽게 말하면 1과 그보다 약간 큰 수를 구분할 수 있는 최소한의 간격을 의미한다.

이 값은 아주 작은 값이라서, 보통 부동소수점 비교 연산에서 사실상 같다고 볼 수 있는 범위를 결정할 때 활용한다. 예를 들어 두 수 ab의 차이가 Number.EPSILON 보다 작다면, 이를 사실상 같은 값으로 간주하는 것이다.

var result = 0.2 - 0.3 + 0.1;
result; // 2.7755575615628914e-17
result < Number.EPSILON; // true

위의 예시에서 0.2 - 0.3 + 0.1의 결과는 고정소수점 연산에선 0이지만 부동소수점 연산에선 2.7755575615628914e-17이 된다(소수점 표현으로는 0.000000000000000027755575615628914). 그리고 이 값은 Number.EPSILON보다도 작다.

ℹ️ 엡실론Εε은 그리스어 알파벳의 다섯째 글자다.

Number.MAX_SAFE_INTEGER

자바스크립트에서 안전하게 표현할 수 있는 가장 큰 정수. 2의 53제곱에 1을 뺀 값으로 9007199254740991이다(약 구천조). 여기서 '안전'하다는 말은 이 값을 넘어가면 에러가 발생한다는 뜻이 아니라, 수학적으로 부정확한(mathematically incorrect) 연산 결과가 나온다는 뜻이다.

자바스크립트의 숫자 타입 Number는 이중 정밀도 부동 소수점 형식을 사용하여 64비트로 숫자를 표현한다. 이 형식은 53비트의 정밀도를 제공하기 때문에, 정확하게 표현할 수 있는 정수의 범위는 -(2^53 - 1)부터 2^53 - 1까지다. 이 범위를 넘어서는 정수는 정확하게 표현되지 않거나 정밀도 손실이 발생할 수 있다.

typeof Number.MAX_SAFE_INTEGER; // "number" 
Number.MAX_SAFE_INTEGER; // 9007199254740991

var unsafeNumber1 = Number.MAX_SAFE_INTEGER + 1;

unsafeNumber1; // 9007199254740992
Number.MAX_SAFE_INTEGER === unsafeNumber1; // false

var unsafeNumber2 = unsafeNumber1 + 1;

unsafeNumber2; // 9007199254740992
unsafeNumber1 === unsafeNumber2; // true
unsafeNumber2 - unsafeNumber1; // 0

위 예시를 보면 9007199254740991 보다 큰 number 값의 비교와 연산을 제대로 처리하지 못한다.

관련 함수로 Number.isSafeInteger()가 있다. 그리고 만약 Number.MAX_SAFE_INTEGER를 초과하는 정수를 다뤄야 한다면 BigInt 타입을 쓰자.

Number.MAX_VALUE

자바스크립트에서 표현할 수 있는 가장 큰 양의 부동소수점 수를 나타내는 상수.

Number.MAX_VALUE; // 1.7976931348623157e+308

var foo = Number.MAX_VALUE + 1000;
foo === Number.MAX_VALUE; // true

Number.MAX_VALUE + Number.MAX_VALUE; // Infinity
Number.MAX_VALUE * 2; // Infinity

1.7976931348623157e+3081.7976931348623157 x (10^308) 이므로:

179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

…가 된다. 그런데 사실 이 값은 근사치고, 정확한 값은 2^1024 - 2^971이며, 고정 소수점 표기법으로:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368

이라 한다… 🙄

Number.MAX_SAFE_INTEGER와 비교

Number.MAX_SAFE_INTEGER < Number.MAX_VALUE; // true

Number.MAX_VALUE는 매우 큰 부동소수점 수의 한계를 나타내며, Number.MAX_SAFE_INTEGER보다 훨씬 크다.

Number.MIN_SAFE_INTEGER

자바스크립트에서 안전하게 표현할 수 있는 가장 작은 정수. 반환하는 값은 -(2^53 - 1) 혹은 -9007199254740991이다. 여기서 '안전'하다는 말은 Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER 범위 내의 정수들이 Number 타입(IEEE 754 표준에 따른 64비트 부동소수점 숫자)으로 정확하게 표현되고, 연산 과정에서 정밀도 손실 없이 사용할 수 있다는 것을 의미한다.

typeof Number.MIN_SAFE_INTEGER; // "number"
Number.MIN_SAFE_INTEGER - 1; // -9007199254740992

var unsafeNumber1 = Number.MIN_SAFE_INTEGER - 1;

unsafeNumber1; // -9007199254740992
Number.MIN_SAFE_INTEGER === unsafeNumber1; // false

var unsafeNumber2 = unsafeNumber1 - 1;

unsafeNumber2; // -9007199254740992
unsafeNumber1 === unsafeNumber2; // true
unsafeNumber1 - unsafeNumber2; // 0

Number.MIN_VALUE

자바스크립트에서 표현할 수 있는 가장 작은 양의 부동소수점 수를 나타낸다.

Number.MIN_VALUE; // 5e-324

5e-3245 x (10^-324)이다. 그러니까 소수점 뒤에 323개의 0이 이어지고 마지막에 5가 오는 값이다:

0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005

그런데 사실 이 값도 MAX_VALUE처럼 근사치고, 정확한 값은 2^-1074이며, 고정 소수점 표기법으로:

0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625

이라 함… 🙄

Number.MIN_SAFE_INTEGER와 비교

Number.MIN_SAFE_INTEGER < Number.MIN_VALUE; // true

Number.MIN_VALUE0에 매우 가까운 양의 값이고, Number.MIN_SAFE_INTEGER는 절댓값이 매우 큰 음의 정수다. 따라서 Number.MIN_SAFE_INTEGER가 훨씬 작다.

Number.EPSILON과 비교

Number.MIN_VALUE < Number.EPSILON; // true

MIN_VALUE5e-324, EPSILON2.220446049250313e-16이다.

지수 부분만 비교해봐도, MIN_VALUE10^-324, EPSILON10^-16이므로 EPSILON이 훨씬 크다.

Number.NaN

'수가 아님'을 나타내는 값인 NaN을 의미하는 상수. 전역 객체의 NaN과 동일한 값이다. 수학 연산의 결과가 수가 될 수 없음을 나타낼 때 쓰인다.

NaN은 자신을 포함한 어떤 값과도 같지 않다. 일치 비교나 동등 비교로 NaN인지 알 수 없다는 말이다. 따라서 NaN인지 판단할 때는 Number.isNaN() 또는 isNaN() 함수를 사용해야 한다.

Number.NaN; // NaN

Number.NaN === NaN; // false
NaN === NaN; // false

isNaN(Number.NaN); // true
isFinite(Number.NaN); // false

typeof NaN"number"으로 평가된다. '수가 아님'을 의미하더라도 표현 방식 자체는 64비트 부동소수점이며, NaN도 내부적으로는 숫자 타입의 표현 방식(부호, 지수, 가수)을 사용하기 때문이라고 한다.

typeof NaN; // "number"

Number.NEGATIVE_INFINITY

음의 무한대를 나타내는 상수. 수학적으로 표현하면 -∞

Number.NEGATIVE_INFINITY; // -Infinity 
Number.NEGATIVE_INFINITY === -Infinity; // true

Number.NEGATIVE_INFINITY * 2; // -Infinity
Number.NEGATIVE_INFINITY * 2 === Number.NEGATIVE_INFINITY; // true

표현 가능한 수의 범위를 음의 방향으로 초과하는 연산은 -Infinity를 반환한다:

-1e308 * 2; // -Infinity 
-Number.MAX_VALUE * 2; // -Infinity

특징으로, 음의 무한대와 어떤 유한한 수를 더하거나 빼더라도 결과는 여전히 음의 무한대라는 것, 모든 유한한 수보다 작다는 것, 그리고 음의 무한대에서 음의 무한대를 빼거나 양의 무한대를 더한 결과는 NaN이라는 것이 있다:

Number.NEGATIVE_INFINITY + 100; // -Infinity
Number.NEGATIVE_INFINITY - 100; // -Infinity

Number.NEGATIVE_INFINITY < -100; // true
Number.NEGATIVE_INFINITY < Number.MIN_SAFE_INTEGER; // true
Number.NEGATIVE_INFINITY < Number.MIN_VALUE; // true
Number.NEGATIVE_INFINITY < Number.EPSILON; // true 

Number.NEGATIVE_INFINITY - Number.NEGATIVE_INFINITY; // NaN
Number.NEGATIVE_INFINITY + Number.POSITIVE_INFINITY; // NaN

Number.POSITIVE_INFINITY

양의 무한대를 나타내는 상수. 전역 변수 Infinity와 동일한 값이다. 수학적 표현은

Number.POSITIVE_INFINITY; // Infinity
Number.POSITIVE_INFINITY === Infinity; // true

Number.POSITIVE_INFINITY * 2; // Infinity
Number.POSITIVE_INFINITY * 2 === Number.POSITIVE_INFINITY; // true

10으로 나누거나, 표현 가능한 수의 범위를 초과하는 연산은 Infinity를 반환한다:

1 / 0; // Infinity
1e308 * 2; // Infinity
Number.MAX_VALUE * 2; // Infinity

특징으로, 양의 무한대에 어떤 유한한 수를 더하거나 빼더라도 결과는 여전희 양의 무한대라는 것, 모든 유한한 수보다 크다는 것, 양의 무한대에서 양의 무한대를 빼거나 음의 무한대를 더한 결과는 NaN이라는 것이 있다:

Number.POSITIVE_INFINITY + 100; // Infinity
Number.POSITIVE_INFINITY - 100; // Infinity 

100 < Number.POSITIVE_INFINITY; // true 
Number.MAX_SAFE_INTEGER < Number.POSITIVE_INFINITY; // true
Number.MAX_VALUE < Number.POSITIVE_INFINITY; // true

Number.POSITIVE_INFINITY - Number.POSITIVE_INFINITY; // NaN
Number.POSITIVE_INFINITY + Number.NEGATIVE_INFINITY; // NaN

스태틱 메서드

Number.isFinite()

주어진 값이 유한한 수인지 확인하는 메서드.

Number.isFinite(value)

value가 숫자이며 Infinity, NaN, undefined가 아니면 true를 반환한다:

Number.isFinite(123); // true
Number.isFinite(-123.45); // true
Number.isFinite(0); // true
Number.isFinite(0x12); // true

Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite(NaN); // false
Number.isFinite(undefined); // false

전역 내장 함수인 isFinite()와 다르게 암묵적 타입 변환은 발생하지 않는다:

Number.isFinite(null); // false
Number.isFinite(''); // false
Number.isFinite('123'); // false
Number.isFinite(' '); // false
Number.isFinite(true); // false
Number.isFinite(false); // false
Number.isFinite([]); // false

isFinite(null); // true
isFinite(''); // true
isFinite('123'); // true
isFinite(' '); // true
isFinite(true); // true
isFinite(false); // true
isFinite([]); // true

Number.isInteger()

주어진 값이 정수인지 판단하는 메서드. 값이 유한한 수이고 소수점이 없거나 소수점 아래가 0이면 true를 반환한다.

Number.isInteger(5); // true
Number.isInteger(5.0); // true
Number.isInteger(5.5); // false
Number.isInteger(5.5); // false
Number.isInteger(NaN); // false
Number.isInteger(Infinity); // false

MDN의 설명에 따르면 이 메서드는 특이사항이 몇 가지 있다.

우선 소수점 아래 값이 너무 작으면 오차가 발생한다. 가령 5.0000000000000001은 실제 정수가 아니지만 true를 반환하는데, 소수점 아래인 0.0000000000000001(= 1e-16)은 정수가 아니지만 Number.EPSILON(= 2.220446049250313e-16)보다 작아서 정밀도 한계로 인해 정수로 간주되는 경우다:

우선 소수점 아래 값이 너무 작으면 오차가 발생한다. 예를 들어, 5.0000000000000001은 실제로는 정수가 아니지만 true를 반환한다. 소수점 아래 값 0.0000000000000001(= 1e-16)이 Number.EPSILON(약 2.220446049250313e-16)보다 작아 정밀도 한계로 인해 정수로 간주되는 경우다:

Number.isInteger(5.0000000000000001); // true

그리고 Number.MAX_SAFE_INTEGER9.007199254740991e+15와 자리수 기준으로 근접한 수에 도달하면 정밀도 손상이 발생하여 정수 판단을 제대로 하지 못한다. 이것은 소수점 아래를 표현할 비트가 부족하여 발생하는 현상이다:

Number.isInteger(4500000000000000.5); // false
Number.isInteger(4500000000000000.1); // true

Number.isNaN()

주어진 값이 NaN인지 판단하는 메서드.

Number.isNaN(NaN); // true
Number.isNaN(5); // false
Number.isNaN('5'); // false

전역 함수 isNaN()보다 엄격한(원문: robust) 버전으로, isNaN()과 다르게 정확히 NaN일 때만 true를 반환한다:

Number.isNaN('not a number'); // false
Number.isNaN('false'); // false
Number.isNaN(undefined); // false
Number.isNaN({}); // false

isNaN('not a number'); // true (숫자로 변환 불가)
isNaN('false'); // true (문자열 "false"는 숫자로 변환 불가)
isNaN(undefined); // true
isNaN({}); // true

ℹ️ NaN은 비교 연산에서 false로 평가되기 때문에, 동등 연산자(==)나 일치 연산자(===)로 판단할 수 없다.

Number.isSafeInteger()

주어진 값이 정밀도 오차 없이 표현 가능한 정수인지 여부를 판단하는 메서드. Number.MIN_SAFE_INTEGERNumber.MAX_SAFE_INTEGER의 사이에 있는 정수면 true를 반환한다.

Number.isSafeInteger(100); // true
Number.isSafeInteger(3.14); // false
Number.isSafeInteger(Number.MAX_SAFE_INTEGER); // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1); // false
Number.isSafeInteger(Number.MIN_SAFE_INTEGER); // true
Number.isSafeInteger(Number.MIN_SAFE_INTEGER - 1); // false

Number.parseFloat()

주어진 값을 부동 소수점 형식의 숫자로 변환한다. 전역 함수 parseFloat()와 동일한 함수다.

이 메서드는 파라미터를 string으로 간주하며, 맨 앞의 공백을 무시한다. 공백이 아닌 첫 번째 문자를 number로 변환할 수 없으면 NaN을 반환한다:

Number.parseFloat('0'); // 0
Number.parseFloat('1234'); // 1234
Number.parseFloat('3.14159265'); // 3.14159265
Number.parseFloat(Number.MIN_VALUE); // 5e-324

const f = Number.parseFloat('1.234');
Object.getPrototypeOf(f); // Number { 0 }

숫자가 이어지는 도중 문자를 만나면, 그때까지의 유효한 숫자만 잘라낸다:

Number.parseFloat('4a'); // 4
Number.parseFloat('48a'); // 48
Number.parseFloat('4.a'); // 4
Number.parseFloat('4.32a'); // 4.32
Number.parseFloat('4.3219876a'); // 4.3219876
Number.parseFloat(null); // NaN
Number.parseFloat(undefined); // NaN

Number.parseInt()

문자열을 정수(Integer)로 변환한다. 주어진 문자열의 맨 앞부터 이어지는 공백은 무시하며, 소수점 이하는 버린다. 전역 함수 paseInt()와 동일한 함수다.

Number.parseInt(string)
Number.parseInt(string, radix)
  • string: 정수로 변환할 값. 공백이 아닌 첫 번째 문자를 number로 변환할 수 없으면 NaN을 반환한다.
  • radix: 진법의 기수. 생략하면 string0x로 시작할 때만 16진수로, 나머지는 10진수로 해석한다.
Number.parseInt('123'); // 123
Number.parseInt("42.7"); // 42
Number.parseInt([1]); // 1
Number.parseInt([1, 2]); // 1
Number.parseInt('a'); // NaN
Number.parseInt('   123'); // 123
Number.parseInt('123abc'); // 123
Number.parseInt('abc123'); // NaN
Number.parseInt('11', 2); // 3
Number.parseInt('ff', 16); // 255
Number.parseInt(null); // NaN
Number.parseInt(undefined); // NaN

Number()와 다른점

Number()는 소수점 처리가 가능하고, NaN으로 판단하는 게 약간 다르다:

Number([1, 2]); // NaN
Number('123abc'); // NaN
Number(null); // 0
Number(undefined); // NaN

인스턴스 메서드

Number.prototype.toExponential()

TODO

Number.prototype.toFixed()

부동 소수점으로 다뤄지고 있는 소수점 아래의 수를 고정 소수점으로 변환하여 표시하는 메서드.

number.toFixed()
number.toFixed(digits)
  • digits: 소수점 아래 자릿수. 0부터 100까지 지정할 수 있고 생략하면 0이다.

Number 인스턴스의 값을 지정한 소수점 아래 자릿수만큼의 길이를 갖는 문자열로 반환한다:

(0.55).toFixed(20); // "0.55000000000000004441" 

만약 소수점 아래의 수가 지정한 길이보다 길면 반올림하여 반환한다:

(0.1).toFixed(30); // "0.100000000000000005551115123126" 
(0.1).toFixed(18); // "0.100000000000000006" 

MDN에선 이를 고정 소수점 표기법(fixed-point notation)이라 설명한다.

Number.prototype.toLocaleString()

TODO

Number.prototype.toPrecision()

TODO

Number.prototype.toString()

TODO

Number.prototype.valueOf()

TODO