Number

Number (숫자)

Number 값은 37이나 -9.25 같은 부동소수점 숫자를 나타냅니다. Number 생성자는 숫자 작업을 위한 상수와 메서드를 포함합니다. 다른 타입의 값은 Number() 함수를 사용해 숫자로 변환할 수 있습니다. 원문은 MDN의 JavaScript 내장 객체 참고 문서입니다.

출처: Number - JavaScript | MDN

본문

Number 값은 37이나 -9.25 같은 부동소수점(fractional) 숫자를 나타냅니다. Number 생성자는 숫자를 다루는 상수와 메서드를 포함합니다. 다른 타입의 값은 Number() 함수를 사용해 숫자로 변환할 수 있습니다.

숫자는 가장 흔히 2553.14159 같은 리터럴 형태로 표현됩니다. lexical grammar에 더 상세한 참조가 있습니다.

255; // 255
255.0; // 같은 숫자
255 === 255.0; // true
255 === 0xff; // true (16진수 표기)
255 === 0b11111111; // true (2진수 표기)
255 === 0.255e3; // true (10진 지수 표기)

JavaScript 코드에서 37 같은 숫자 리터럴은 정수가 아니라 부동소수점 값입니다. 일상적으로 쓰는 별도의 정수 타입은 없습니다. (JavaScript에는 BigInt 타입도 있지만, 일상적인 사용에서 Number를 대체하도록 설계된 것은 아닙니다. 37은 여전히 숫자이지 BigInt가 아닙니다.)

함수로 사용될 때 Number(value)는 문자열이나 다른 값을 Number 타입으로 변환합니다. 값을 변환할 수 없으면 NaN을 반환합니다.

Number("123"); // 123
Number("123") === 123; // true
Number("unicorn"); // NaN
Number(undefined); // NaN

Number 인코딩 (Number encoding)

JavaScript Number 타입은 Java나 C#의 double처럼 배정밀도(double-precision) 64비트 2진 형식의 IEEE 754 값입니다. 즉 분수 값을 표현할 수 있지만 저장된 숫자의 크기와 정밀도에는 한계가 있습니다. 간단히 말해 IEEE 754 배정밀도 숫자는 64비트로 세 부분을 표현합니다.

  • 부호(sign): 1비트 (양수 또는 음수)
  • 지수(exponent): 11비트 (-1022 ~ 1023)
  • 가수(mantissa): 52비트 (0과 1 사이 숫자 표현)

가수(significand라고도 함)는 실제 값(유효 숫자)을 나타내는 숫자의 부분입니다. 지수는 가수에 곱해질 2의 거듭제곱입니다. 과학적 표기법으로 생각하면 Number = (-1)^sign × (1 + mantissa) × 2^exponent입니다. 가수는 52비트로 저장되며, 이진 분수 숫자에서 1.... 뒤의 자릿수로 해석됩니다. 따라서 가수의 정밀도는 2^-52(Number.EPSILON으로 얻을 수 있음), 즉 약 15~17개의 유효 십진 자릿수이며, 그 수준을 넘는 연산은 반올림의 대상이 됩니다.

숫자가 담을 수 있는 가장 큰 값은 2^1023 × (2 - 2^-52)이며(Number.MAX_VALUE로 얻을 수 있음), 그보다 큰 값은 특수 숫자 상수 Infinity로 대체됩니다. 정수는 가수가 선행 1을 포함해 53비트만 담을 수 있으므로, 정밀도 손실 없이 표현할 수 있는 범위는 -2^53 + 1부터 2^53 - 1까지(포함, Number.MIN_SAFE_INTEGERNumber.MAX_SAFE_INTEGER로 얻음)입니다. 더 자세한 내용은 ECMAScript 표준에 설명되어 있습니다.

Number 강제 변환 (Number coercion)

숫자를 기대하는 많은 내장 연산은 먼저 인자를 숫자로 강제 변환합니다. 그 과정은 다음과 같이 요약됩니다.

  • 숫자는 그대로 반환됩니다.
  • undefinedNaN이 됩니다.
  • null0이 됩니다.
  • true1, false0이 됩니다.
  • 문자열은 숫자 리터럴을 담고 있는 것처럼 파싱해 변환됩니다. 파싱에 실패하면 NaN이 됩니다. 실제 숫자 리터럴과는 약간의 차이가 있습니다 — 앞뒤 공백/라인 터미네이터는 무시되고, 선행 0 자릿수는 8진수 리터럴이 되게 하지 않으며(strict mode에서 거부되지도 않음), 문자열 시작의 +-는 부호를 나타내는 데 허용되며(실제 코드에서는 리터럴의 일부처럼 보이지만 별개의 단항 연산자임), Infinity-Infinity는 리터럴로 인식되며(실제 코드에서는 전역 변수), 빈 문자열 또는 공백만의 문자열은 0으로 변환되고, 숫자 구분자(numeric separator)는 허용되지 않습니다.
  • BigInt는 의도치 않은 암묵적 변환으로 인한 정밀도 손실을 막기 위해 TypeError를 던집니다.
  • Symbol은 TypeError를 던집니다.
  • 객체는 먼저 [Symbol.toPrimitive]()("number" 힌트로), valueOf(), toString() 메서드를 이 순서대로 호출해 기본형으로 변환한 뒤, 그 결과 기본형을 숫자로 변환합니다.

JavaScript에서 거의 같은 효과를 얻는 두 가지 방법이 있습니다. 단항 더하기 +x는 위의 숫자 강제 변환 단계를 정확히 수행해 x를 변환합니다. Number() 함수 Number(x)는 같은 알고리즘으로 x를 변환하되, BigInt가 TypeError를 던지지 않고 (정밀도 손실 가능성과 함께) 그 숫자 값을 반환합니다. Number.parseFloat()Number.parseInt()Number()와 비슷하지만 문자열만 변환하고 파싱 규칙이 약간 다릅니다. 예를 들어 parseInt()는 소수점을 인식하지 않고, parseFloat()0x 접두사를 인식하지 않습니다.

정수 변환 (Integer conversion)

일부 연산은 정수를 기대합니다. 특히 배열/문자열 인덱스, 날짜/시간 구성 요소, 숫자 진법(radix)을 다루는 것들이 그렇습니다. 위의 숫자 강제 변환 단계를 수행한 뒤 결과는 (소수 부분을 버려) 정수로 자릅니다. 숫자가 ±Infinity이면 그대로 반환되고, NaN이나 -0이면 0으로 반환됩니다. 따라서 결과는 항상 정수(-0이 아닌)이거나 ±Infinity입니다. 특히 정수로 변환할 때 undefinednull 모두 0이 됩니다. undefinedNaN으로 변환되고, 이것 또한 0이 되기 때문입니다.

고정 너비 숫자 변환 (Fixed-width number conversion)

JavaScript에는 정수 숫자의 2진 인코딩을 다루는 저수준 함수가 있습니다. 가장 주목할 만한 것은 비트 연산자와 TypedArray 객체입니다. 비트 연산자는 항상 피연산자를 32비트 정수로 변환합니다. 이런 경우 값이 숫자로 변환된 뒤, 소수 부분을 먼저 버리고 정수의 2의 보수(two's complement) 인코딩에서 최하위 비트를 취해 주어진 너비로 정규화됩니다.

new Int32Array([1.1, 1.9, -1.1, -1.9]); // Int32Array(4) [ 1, 1, -1, -1 ]
new Int8Array([257, -257]); // Int8Array(2) [ 1, -1 ]
// 257 = 0001 0000 0001 = 0000 0001 (mod 2^8) = 1
// -257 = 1110 1111 1111 = 1111 1111 (mod 2^8) = -1 (signed integer)
new Uint8Array([257, -257]); // Uint8Array(2) [ 1, 255 ]
// -257 = 1110 1111 1111 = 1111 1111 (mod 2^8) = 255 (unsigned integer)

생성자 및 정적 속성/메서드 (Constructor, static properties, static methods)

  • Number() — Number 객체를 만듭니다. 함수로 호출하면 Number 타입의 기본형 값을 반환합니다.
  • Number.EPSILON — 두 표현 가능한 숫자 사이의 가장 작은 간격.
  • Number.MAX_SAFE_INTEGER — JavaScript의 최대 안전 정수 (2^53 - 1).
  • Number.MAX_VALUE — 가장 큰 양의 표현 가능한 숫자.
  • Number.MIN_SAFE_INTEGER — JavaScript의 최소 안전 정수 (-(2^53 - 1)).
  • Number.MIN_VALUE — 가장 작은 양의 표현 가능한 숫자 — 즉 0에 가장 가까운 양수(실제로 0은 아님).
  • Number.NaN — 특수한 "Not a Number" 값.
  • Number.NEGATIVE_INFINITY — 음의 무한대를 나타내는 특수 값. 오버플로 시 반환.
  • Number.POSITIVE_INFINITY — 무한대를 나타내는 특수 값. 오버플로 시 반환.
  • Number.isFinite() — 전달된 값이 유한한 숫자인지 결정.
  • Number.isInteger() — 전달된 값이 정수인지 결정.
  • Number.isNaN() — 전달된 값이 NaN인지 결정.
  • Number.isSafeInteger() — 전달된 값이 안전 정수인지 결정.
  • Number.parseFloat() / Number.parseInt() — 전역 parseFloat()/parseInt() 함수와 같음.

인스턴스 속성 및 메서드 (Instance members)

Number.prototype에 정의되어 모든 Number 인스턴스가 공유하는 constructor가 있습니다. 인스턴스 메서드로는 지수 표기법 문자열을 반환하는 toExponential(), 고정 소수점 표기법 문자열을 반환하는 toFixed(), 언어별 표현 문자열을 반환하는 toLocaleString(), 지정 정밀도로 고정 소수점 또는 지수 표기법 문자열을 반환하는 toPrecision(), 지정 진법("base")으로 객체를 나타내는 문자열을 반환하는 toString(), 지정 객체의 기본형 값을 반환하는 valueOf()가 있습니다.

예제 (Examples)

숫자 변수에 값 할당.

const biggestNum = Number.MAX_VALUE;
const smallestNum = Number.MIN_VALUE;
const infiniteNum = Number.POSITIVE_INFINITY;
const negInfiniteNum = Number.NEGATIVE_INFINITY;
const notANum = Number.NaN;

Number 정수 범위.

const biggestInt = Number.MAX_SAFE_INTEGER; // (2**53 - 1) => 9007199254740991
const smallestInt = Number.MIN_SAFE_INTEGER; // -(2**53 - 1) => -9007199254740991

JSON으로 직렬화된 데이터를 파싱할 때 이 범위를 벗어나는 정수 값은 JSON 파서가 이를 Number 타입으로 강제 변환하면서 손상될 수 있습니다. 가능한 해결책은 String을 사용하는 것입니다. 더 큰 숫자는 BigInt 타입으로 표현할 수 있습니다.

Number()로 Date 객체 변환.

const d = new Date("1995-12-17T03:24:00");
console.log(Number(d)); // 819199440000

숫자 문자열과 null을 숫자로 변환.

Number("123");      // 123
Number("12.3");     // 12.3
Number("12.00");    // 12
Number("123e-1");   // 12.3
Number("");         // 0
Number(null);       // 0
Number("0x11");     // 17
Number("0b11");     // 3
Number("0o11");     // 9
Number("foo");      // NaN
Number("100a");     // NaN
Number("-Infinity");// -Infinity

사양 및 호환성

Number는 ECMAScript® 2027 Language Specification의 # sec-number-objects 절에 정의되어 있습니다. Baseline "Widely available"로 분류되어 2015년 7월부터 브라우저 전반에서 사용 가능했습니다.

더 알아보기