Front-End/JavaScript

[You Don't Know JS] #03 자바스크립트의 숫자

koh1018 2022. 4. 5. 22:43
반응형

 

 

/* 이 글은 카일 심슨의 You Don't Know JS를 읽으며 배운 것들을 개인적으로 정리하고 기록하기 위한 글입니다. */

 

 

 

자바스크립트의 숫자 타입은 number 뿐이다. 정수, 부동 소숫점 숫자를 아우른다.

즉 자바스크립트에서 42.0'정수' 42와 같다.

 

숫자는 10진수가 디폴트이다.

 

아주 크거나 작은 숫자는 지수형(Exponent Form)으로 표시한다. (toExponential() 메서드로 표현할 수 있다.)

var a = 5E10;
a;	// 50000000000
a.toExponential();	// "5e+10" 문자열로 반환

(참고 : e는 10^n을 의미한다. E10은 10^10이다.)

 

숫자 값은 Number 객체 래퍼로 박싱할 수 있기 때문에 Number.prototype 메서드로 접근할 수도 있다.

예를 들면 toFixed() 메서드는 지정한 소수점 이하 자릿수까지 숫자를 나타낸다.

var a = 42.59;

a.toFixed(0); // "43"
a.toFixed(1); // "42.6"
a.toFixed(2); // "42.59"
a.toFixed(3); // "42.590"

(참고 : toFixed()는 파라매터로 넣은 자릿수 + 1의 자리에서 반올림해서 표시한다.)

 

비슷한 메서드로 toPrecision()이 있다.

유효 숫자 개수를 지정할 수 있다.

var a = 42.59;

a.toPrecision(1); // "4e+1"
a.toPrecision(2); // "43"
a.toPrecision(3); // "42.6"
a.toPrecision(4); // "42.59"
a.toPrecision(5); // "42.590"

 

숫자 리터럴은 2진, 8진, 16진 등 다른 진법으로도 나타낼 수 있다.

// 2진수
0b11110011;	// 243의 2진수

// 8진수
0o363;	// 243의 8진수

// 16진수
0xf3;	// 243의 16진수

2진수, 8진수, 16진수는 각각 0b, 0o, 0x를 앞에 붙여 표현할 수 있다.

 

 

 


 

 

이진 부동 소숫점 숫자에는 부작용이 있다.

0.1 + 0.2 === 0.3;	// false

위 수식을 보면 상식적으로 true가 나와야 한다. 하지만 false가 나온다.

그 이유는 0.1 + 0.2가 0.3이 아닌 0.30000000000000004에 가까운 값이 나오기 때문이다.

(이를 위해 수십 년 동안 갖가지 대안이 제시되었지만 어느 것도 채택되지 않았고 앞으로도 사정은 비슷할 것 같다고 한다...)

이는 작은 숫자 값을 다룰 때 발생하는 문제점이다.

만약 정수 또는 큰 숫자를 사용한다면 크게 신경쓰지 않아도 된다.

 

그렇다면 0.1 + 0.2 와 0.3 은 어떻게 비교해야 할까?

가장 일반적으로는 허용 공차(Tolerance)로 처리하는 방법이 있다.

이렇게 미세한 오차를 '머신 입실론(Machine Epsilon)'이라고 하는데, ES6부터는 이 값이 Number.EPSILON으로 미리 정의되어 있다.

function numbersCloseEnoughToEqual(n1, n2) {
  return Math.abs(n1 - n2) < Number.EPSILON;
}

var a = 0.1 + 0.2;
var b = 0.3;

numbersCloseEnoughToEqual(a, b);  // true
numbersCloseEnoughToEqual(0.0000001, 0.0000002);  // false

위와 같이 값이 같은지 비교하는 함수를 정의해 파라매터로 들어온 두 수의 차이가 입실론보다 작다면 true를 반환해주도록 할 수 있다.

 

EPSILON말고도 부동 소숫점 숫자의 최댓값을 정의한 Number.MAX_VALUE (대략 1.798e+308), 최솟값을 정의한 Number.MIN_VALUE (대략 5e-324 / 음수는 아니지만 거의 0에 가까움)이 있다.

 

정수는 Number.MAX_VALUE보다 작은 수준에서 안전 값의 범위가 정해져 있는데, 2^53-1으로 약 9천 조이다.

이 값은 ES6에서 Number.MAX_SAFE_INTEGER로 정의한다.

최솟값은 Number.MIN_SAFE_INTEGER로 정의한다. (-9007199254740991)

 

 

 


 

 

ES6부터는 Number.isInteger()로 값의 정수 여부를 확인할 수 있다.

Number.isInteger(42); // true
Number.isInteger(42.000); // true
Number.isInteger(42.3); // false

위에서 봤던 안전한 정수 여부는 Number.isSafeInteger()로 체크할 수 있다.

 

반응형