해당 글은 'YOU DON`T KNOW JS(타입과 문법, 스코프와 클로저)' 라는 책을 읽으며
나름의 정리를 하는 글입니다.
* 자바스크립트의 숫자 타입은 number가 유일하며 '정수(Integer)', '부동 소수점 숫자(Fractional Decimal Number)'를
아우름.
자바스크립트 number도 IEEE 754 표준을 따르며, 그중에서도 정확히는 '배 정도(Double Precision)'
표준 포맷(64비트 바이너리)을 사용.
* 자바스크립트 숫자 리터럴은 10진수 리터럴로 표시.
var a = 42;
var b = 42.3;
소수점 앞 정수가 0이면 생략 가능.
var a = 0.42;
var b = .42;
소수점 이하가 0일 때도 생략 가능.
var a = 0.42;
var b = 42;
42. 처럼 표기하는 건 일반적이지도 않고 다른 사람이 코드를 읽을 때 혼동을 일으킬 수 있으니 별로 좋은 생각은 아니지만 그렇다고 틀린 코드는 아님.
아주 크거나 아주 작은 숫자는 지수형(Exponent Form)으로 표시하며, toExponential() 메서드의 결과 값과 같음.
var a = 5E10;
a; // 50000000000
a.toExponential(); // "5e+10"
var b = a * a;
b; // 2.5e21
var c = 1 / a;
c; // 2e-11
숫자 값은 Number 객체 래퍼(Wrapper)로 박싱(boxfing) 할 수 있기 때문에 Number.prototype 메서드로
접근할 수도 있음.
예를 들면 toFixed() 메서드는 지정한 소수점 이하 자릿수까지 문자열 형태로 반환하며,
원래 값의 소수점 이하보다 더 많은 자릿수를 지정하면 그만큼 0이 우측에 붙음.
var a = 42.59;
a.toFixed(0); // "43"
a.toFixed(1); // "42.6"
a.toFixed(2); // "42.59"
a.toFixed(3); // "42.590"
a.toFixed(4); // "42.5900"
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"
a.toPrecision(6); // "42.5900"
두 메서드는 숫자 리터럴에서 바로 접근할 수 있으므로 굳이 변수를 만들어 할당하지 않아도 됨.
하지만 .이 소수점일 경우엔 프로퍼티 접근자(Accessor)가 아닌 숫자 리터럴의 일부로 해석되므로
. 연산자를 사용할 때는 주의 필요.
// 잘못된 구문
42.toFixed(3); // SyntaxError: Invalid or unexpected token
// 올바른 구문
(42).toFixed(3); // "42.000"
0.42.toFixed(3); // "0.420"
42..toFixed(3); // "42.000"
42 .toFixed(3); // "42.000"
42.toFixed(3)에서 구문 에러가 난 이유는 .이 42. 리터럴(맞는 표현)의 일부가 되어 버려 .toFixed 메서드에
접근할 수단이 없기 때문.
사실 원시 값이 메서드를 직접 호출할 일은 거의 없을뿐더러(거의 없을뿐 나쁘거나 틀렸다는 소리가 아님)
보기에 어색하고 불편하여 가독성이 좋지 않으므로 지양 할 필요가 있음.
Number.prototype을 확장하여 숫자 값 연산 기능을 추가한 라이브러리들도 있다.
하늘에서 10초 동안 돈다발이 비처럼 쏟아지게 하는 10..makeItRain() 같은 코드가 있을지 모를 일이다.
어쨌든 이런 라이브러리를 구해 써도 된다.
큰 숫자는 보통 지수형으로 표시.
var onethousand = 1E3; // 1 * 10^3
var onemilliononehundredthousand = 1.1E6; // 1.1 * 10^6
숫자 리터럴은 2진, 8진, 16진 등 다른 진법으로도 나타낼 수 있음.
0xf3; // 243의 16진수
0xf3; // 위와 같음
0363; // 243의 8진수
ES6 + 엄격모드(Strict Mode)에서는 0363처럼 0을 앞에 붙여 8진수를 표시하지 못한다(새 방식은 바로 다음에 설명한다).
느슨한 모드(Non-Strict Mode)에서는 과거 형식을 계속 쓸 수는 있지만 미래를 생각해서 쓰지 않는게 좋다(이제부턴 엄격 모드에서 코딩해야 하므로).
ES6부터는 다음과 같이 쓸 수도 있음.
0o363; // 243의 8진수
0O363; // 위와 같음
0b11110011; // 243의 2진수
0B11110011; // 위와 같음
0다음 O와 같이 대문자로 할 경우 숫자와 헷갈리므로 소문자로 표기 필요.
* 널리 알려진 이진 부동 소수점 숫자의 부작용(다른 언어는 모두 IEEE 754 표준을 준수하지만,
자바스크립트는 그렇지 않음).
0.1 + 0.2 === 0.3; // false
이진 부동 소수점으로 나타낸 0.1과 0.2를 더한 결과는 0.30000000000000004에 가까울뿐 0.3과 같지 않으므로
비교 결과는 false.
하지만 전체수(Whole Number)(정수)만을 다루는 경우에는 위와 같은 문제는 없음.
전체수(Whole Number)란 0 과 양수를 포함한 숫자.
정수는 다들 알고 있는 것처럼 음수와 0, 양수를 포함한 숫자를 말합니다.
자연수(Natural Number)는 양수만을 가리킵니다.
그래서 부동 소수점 숫자를 다루어야 하는 경우 가장 일반적으로는 미세한 '반올림 오차'를 허용 공차(Tolerance)로
처리하는 방법이 있음.
이렇게 미세한 오차를 '머신 입실론(Machine Epsilon)'이라고 하는데, 자바스크립트 숫자의 머신 입실론은
2.220446049250313e-16(ES6부터는 머신 입실론 값을 Number.EPSILON으로 미리 정의되어 있음)이며
해당 값으로 두 숫자의(반올림 허용 오차 이내의) '동등함(Equality)'을 비교할 수 있음.
머신 입실론은 컴퓨터가 이해할 수 있는 가장 작은 숫자 단위를 말합니다.
컴퓨터는 실수를 이진수의 형태로 저장하기 때문에 1/3과 같은 숫자를 저장하는 것은 불가능합니다. 하지만 대부분의 경우에 무한히 긴 0.3333333...과 같이 표현할 수 있습니다.
그러나 마지막 값은 일반적으로 3이 아니라 2나 4가 됩니다.
이와 같이 컴퓨터가 다룰 수 있는 가장 작은 수, 즉 임계 값을 머신 입실론이라 합니다(출처:컴퓨터인터넷IT용어대사전, 전산용어사전편찬위원회, 2011.1.20, 일진사 http://goo.gl/y5bocj)
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
부동 소수점 숫자의 최댓값은 대략 1.798e+308이고 Number.MAX_VALUE로 정의하며,
최소값은 5e-324로 음수는 아니지만 거의 0에 가까운 숫자고 Number.MIN_VALUE로 정의 함.
* 정수는 Number.MAX_VALUE보다 훨씬 작은 수준에서 안전(Safe)값의 범위가 정해져 있음.
'안전하게' 표현할 수 있는(즉, 표현한 값과 실제 값이 정확하게 일치한다고 장담할 수 있는) 정수는
최대 9007199254740991(ES6부터는 Number.MAX_SAFE_INTEGER로 정의되어 있음),
최소 -9007199254740991(ES6부터는 Number.MIN_SAFE_INTEGER로 정의되어 있음) 임.
* 정수의 '안전 범위'가 대략 9천조(53비트)에 이르지만, (비트 연산(Bitwise Operation처럼))
32비트 숫자에만 가능한 연산이 있으므로 실제 정수의 안전 범위는
Math.pow(-2, 31)(-2147483648)에서 Math.pow(2, 31)-1(2147483647)까지임.
'웹 > 공부' 카테고리의 다른 글
YOU DON`T KNOW JS(타입과 문법, 스코프와 클로저) : 3 (0) | 2022.04.20 |
---|---|
YOU DON`T KNOW JS(타입과 문법, 스코프와 클로저) : 2 (0) | 2022.04.19 |
YOU DON`T KNOW JS(타입과 문법, 스코프와 클로저) : 1 (0) | 2022.04.18 |
JavaScript - The Definitive Guide 6/E(자바스크립트 완벽 가이드) : 5 (0) | 2019.12.10 |
JavaScript - The Definitive Guide 6/E(자바스크립트 완벽 가이드) : 4 (0) | 2019.10.30 |