Modern Javascript 숫자형

[Modern Javascript] 숫자형


본 내용은 모던 자바스크립트 숫자형을 보고 공부, 정리한 내용입니다.

숫자형의 종류

자바스크립트에서 숫자형은 두 가지가 존재한다.

  1. 배정밀도 부동소수점 숫자
    64bit 크기를 갖는다.
    표현 가능한 범위는 2-53 ~ 253 - 1 이다.

  2. BigInt
    배정밀도 부동소수점 숫자 범위로 나타낼 수 없는 범위의 수를 표현할 때 쓰인다.


숫자를 입력하는 다양한 방법

아주 큰 수나 아주 작은 수를 입력할 땐 ‘e’를 사용하여 간단하게 입력할 수 있다.

1
2
3
4
5
6
7
// 10억의 서로 다른 표현
const num1 = 1000000000;
const num2 = 1e9;

// 1 nano의 서로 다른 표현
const num3 = 0.000000001;
const num4 = 1e-9

16진수, 8진수, 2진수 표현

16진수는 숫자 앞에 ‘0x’ 를 붙여서 표현한다.
8진수는 숫자 앞에 ‘0o’ 를 붙여서 표현한다.
2진수는 숫자 앞에 ‘0b’ 를 붙여서 표현한다.

1
2
3
4
5
6
7
const hex = 0xff;
const oct = 0o12;
const bin = 0b11;
console.log(hex, oct, bin);

// 출력 결과
255 10 3

toString(base)

num.toString(base) 는 base 진법으로 num을 표현한 후, 문자형으로 변환한다.

1
2
3
4
let num = 255;

alert( num.toString(16) );  // ff
alert( num.toString(2) );   // 11111111

진법 변환 시 0..9 까지의 숫자와 필요할 경우 A..Z 까지의 알파벳이 쓰인다.
(36진법은 10가지의 숫자와 26가지의 알파벳이 모두 쓰임)

  • 상수의 toString(base) 호출
    변수가 아닌 정수형 상수에 toString(base) 메서드를 사용할 때는 소수점과 메서드 호출 문법을 구분짓기 위해 점을 2개 붙여야 한다.

    1
    2
      12345.toString(2) // error
      12345..toString(2) // correct!
    

어림수 구하기

어림수란 우리가 흔히 알고 있는 올림, 버림(내림), 반올림과 같은 연산을 통해 나온 수를 의미한다.
이와 관련된 내장 함수 몇 가지를 살펴보자.

Math.floor

버림(내림) 함수이다.
Math.floor(3.1) ⇒ 3, Math.floor(-1.1) ⇒ -2 이다.

Math.ceil

올림 함수이다.
Math.ceil(3.1) ⇒ 4, Math.ceil(-1.1) ⇒ -1 이다.

Math.round

반올림 함수이다.
Math.round(3.1) ⇒ 3, Math.round(-1.1) ⇒ -1 이다.

Math.trunc

소수부를 무시하는 함수이다.
Math.trunc(3.1) ⇒ 3, Math.round(-1.1)⇒ -1 이다.
Math.trunc는 Internet Explorer에서 지원하지 않는다.

만약 특정 소수점 아래에 대해 어림수를 구하고 싶다면?

1. 해당 소수점까지 정수형으로 만들고 어림수 내장 함수 사용

예를 들어, 123.4567 숫자를 소수점 아래 둘째 자리까지의 어림수를 구하고 싶다면,
Math.round(123.4567 * 100) / 100 과 같이 계산할 수 있다.

2. toFixed(n) 내장 함수 사용

num.toFixed(n) 내장 함수는 숫자 num의 소수점 n번째 까지의 어림수를 반올림하여 구하고, 이를 문자형으로 리턴한다.
문자형으로 리턴한다는 점에 주의하자. 만약 주어진 숫자의 소수부 길이보다 n이 더 클 경우, 그만큼 0이 붙은 문자형이 리턴된다.

1
2
let num = 12.34;
alert( num.toFixed(5) ); // "12.34000"

부정확한 계산

1. 숫자가 너무 크거나 작은 경우

1
2
alert(1e500); // Infinity
alert(1e-500); // -Infinity

배정밀도 부동소수점 숫자가 표현할 수 있는 범위 (52비트) 를 넘어서면, Infinity 혹은 -Infinity로 변환된다.

2. 정밀도 손실 (loss of precision)

소수점 아래의 숫자는 2진수를 사용하는 컴퓨터의 특성 상 정확하게 표현할 수 없다.

1
2
3
4
5
const num1 = 1.1;
const num2 = 1.1;
alert(num1 + num2 === 2.2); // false

alert(num1.toFixed(20)); // 0.10000000000000000555

정밀도 손실을 최대한 줄이기 위해 해당 수를 어림수로 표현하는 방법이 있다.
위에서 살펴본 특정 소수점에 대한 어림수 만드는 방법과 동일하다.
정밀도 손실 방지를 위해서는 toFixed(n) 메서드 사용이 더 신뢰성 있다.

정밀도 손실 예시

6.35.toFixed(1) 의 결과는 어떻게 나오는지 출력해보자.

1
alert(6.35.toFixed(1)); // 6.3

6.4를 기대했지만 결과는 6.3이다. 6.35를 소수점 아래 20자리까지 출력해보면 아래와 같다.

1
alert(6.35.toFixed(20)); // 6.34999999999999964473

6.35를 2진수로 표현하면 무한소수가 되기 때문이다. 이러한 수의 어림수를 정확하게 계산하기 위해선 최대한 2진수로 표현했을 시 무한소수가 되지 않게 만들어야 한다.

1
alert((6.35 * 10).toFixed(20)); // 63.50000000000000000000

63.5 에서 0.5는 정확히 2-1로 나타낼 수 있기 때문에 정밀도 손실이 없다.
따라서 63.5의 반올림 값을 구한 뒤 10으로 나누면 정밀도 손실을 최소화할 수 있다.

+0 과 -0

1
2
3
4
const num1 = 1e-500;
const num2 = -1e-500;
console.log(num1); // 0
console.log(num2); // -0

자바스크립트에선 0을 포함한 모든 수에 부호를 설정할 수 있다. 따라서 0과 -0이 따로 존재한다.
대부분의 연산에서는 이 둘을 동일하게 취급한다.


isNaN과 isFinite

특수한 숫자형 (Infinity, -Infinity, NaN) 을 탐지하기 위한 내장 함수이다.

isNaN(value)

value를 숫자형으로 변환 후, NaN인지 탐지한다.

1
2
alert( isNaN(NaN) ); // true
alert( isNaN("str") ); // true
  • 주의
    “=== NaN” 과 같이 비교하면 NaN인 수를 잡아낼 수 없다. NaN은 자기 자신을 포함하여 그 어떤 숫자와도 같지 않은 성질을 갖고 있기 때문이다.
    1
      alert(NaN === NaN); // false
    

isFinite(value)

value를 숫자형으로 변환 후, Infinity, -Infinity, NaN이 아니면 true, 맞다면 false 를 리턴한다.

  • 주의
    빈 문자열이나 공백 문자만 있는 문자열은 숫자형으로 변환 시 0으로 변환된다.
    따라서 isFinite(“”); 은 true를 반환한다.

Object.is()

두 값을 비교할 때 사용되는 내장 함수이다.
NaN 간의 비교, 0과 -0의 구분 시 “===” 비교와 차이를 보인다.

  1. Object.is(NaN, NaN) 은 true이다.
  2. Object.is(0, -0) 은 false 이다.

parseInt와 parseFloat

단항 연산자 혹은 Number()를 사용한 숫자형 변환은 엄격하다. 양 끝의 공백을 제외하고 숫자 이외의 문자가 섞여있다면 NaN이 리턴된다.
parseInt와 parseFloat는 이들보다 덜 엄격한 숫자형 변환 함수로, 처음부터 숫자가 아닌 문자가 나올 때까지의 문자를 숫자형으로 변환한다.

1
2
3
4
5
6
7
alert( parseInt('100px') ); // 100
alert( parseFloat('12.5em') ); // 12.5

alert( parseInt('12.3') ); // 12, 정수 부분만 반환됩니다.
alert( parseFloat('12.3.4') ); // 12.3, 두 번째 점에서 숫자 읽기를 멈춥니다.

alert( parseInt('a123') ); // NaN, a는 숫자가 아니므로 숫자를 읽는 게 중지됩니다.

참고로 parseInt(str, radix) 에서 radix는 str을 몇 진법의 수로 판단할 것이냐를 의미한다.
radix = 16이면, str을 16진수 수로 판단하고 이를 숫자형으로 변환한 뒤, 10진수로 변환한 값을 리턴한다.

0%