안녕하세요 이번 시간에는 숫자(Number)에 대해 알아보겠습니다. 숫자도 원시 래퍼 객체(new Number()
)가 있습니다. 그래서 메소드를 가질 수 있습니다. 사실 숫자만으로는 양이 별로 없어서 Math 객체까지 같이 알려드리겠습니다.
숫자
간단한 문제를 풀어봅시다.
var a = 0.1;
var b = 0.2;
a + b; // 뭘까요?
장난하냐고요? 0.3이라고요? 똑똑한 컴퓨터한테 물어봅시다. 컴퓨터는 계산을 틀리지 않으니까요.
a + b; // 0.30000000000000004
네 그렇습니다. 지금까지 인간은 간단한 덧셈조차 못하고 있던겁니다...가 아니라 인간이 계산 중에 유일하게 컴퓨터를 이길 수 있는 분야입니다. 몇몇 프로그래밍 언어들은 소수점을 계산하지 못하는 치명적인 단점을 가지고 있습니다. 대충 이유는 다음과 같습니다. 컴퓨터는 소수를 2진법으로 바꿔서 계산하는데 2진법으로 바꾸면 몇몇 소수(위와 같은 경우)는 무한소수가 됩니다. 저장공간이 정해져있는 컴퓨터는 무한소수의 값을 다 저장하지 못하고 끝부분을 버려 유한소수로 만듭니다. 그 버린 부분 때문에 오차가 발생합니다. 말은 장황해도 뭐 어쨌든 계산을 못한다는 거죠. 그래서 이를 극복하기 위해 다음과 같은 방법을 쓰기도 했습니다.
(10 * a + 10 * b) / 10; // 0.3
a와 b에 10을 곱해 정수로 만든 후 계산한 뒤, 마지막에 10으로 다시 나눠주는 거죠. 번거로운 과정입니다. 하지만 자바스크립트에는 위와 같은 과정을 거치지 않게 해 줄 메소드들이 있습니다.
숫자.toFixed(소수자릿수), 숫자.toPrecision(자릿수)
(a + b).toFixed(2); // '0.30'
0.00125.toPrecision(2); // '0.0013'
1.2356.toFixed(3); // '1.236'
1.2346.toPrecision(2); // '1.2'
toFixed 함수는 지정된 소수자릿수까지 반올림해서 나타냅니다. 문자열로 반환하기 때문에 숫자로 바꿔주는 작업이 필요합니다. 소수점 연산을 정확하게 만들려면 자릿수를 지정해줘야합니다.
toPrecision은 지정된 자릿수만큼만 표현해 문자열로 반환합니다. 만약 소수일 경우 앞의 0들은 무시합니다. 0.00125.toPrecision(2)
은 두 자릿수까지만 표현해야 하는데, 소수이기 때문에 0.0이 아니라 0.0013이 됩니다. 앞의 0들을 다 무시했기 때문에 남은 125에서 반올림 후 두 자릿수를 자른 겁니다.
isNaN(숫자)
3 / "가"; // NaN
isNaN(3/"가"); // true
안에 넣은 숫자가 진짜 숫자인지 테스트합니다. true/false로 알려줍니다. NaN이라는 값이 처음 나왔는데요. NaN이란 Not a Number로 '3 나누기 "가"' 처럼 숫자가 아닌 계산을 하면 NaN 값이 나옵니다. NaN도 하나의 숫자값입니다. isNaN은 숫자가 아닌 값들에 대해 true를 알려줍니다. 하지만 isNaN은 지금 현재 문제가 있는 함수라고 소문나 있습니다.
NaN의 특별한 성질 중 하나는 자바스크립트에서 유일하게 자기 자신과 같지 않은 값이라는 겁니다.
NaN == NaN; // false
재밌는 놈입니다. 위에 isNaN 함수보다 이 방법을 사용하는 게 더 판별에 효과적입니다.
Infinity
내친김에 숫자값 하나 더 알아보고 가죠.
3 / 0; // Infinity
-3 / 0; // -Infinity
0으로 나누었을 경우 Infinity 값이 나옵니다. 말 그대로 무한입니다. 그리고 음의 무한일 경우에는 -Infinity가 됩니다.
parseInt(숫자, 진법), parseFloat(숫자)
parseInt("1등", 10); // 1
parseFloat("0.5달러"); // 0.5
parseFloat(0.3.toFixed(2)); // 0.3
자주 쓰일 두 종류는 외워두는 게 좋습니다. parseInt는 정수로, parseFloat는 실수로 바꿔줍니다. 아까 toFixed와 toPrecision은 모두 문자열을 반환하는데, 이 값을 다시 숫자로 만드려면 parseInt, parseFloat을 해줘야합니다. 참고로 문자열이더라도 숫자로 시작하면 뒤에 글자들은 없애고 숫자로 바꿔줍니다. 숫자로 시작하지 않으면 NaN이 됩니다.
Number(아무거나)
Number("1"); // 1
Number("0.5달러"); // NaN
Number객체 자체가 함수로 쓰일 수 있습니다(위에서 말한 원시 래퍼 객체와는 조금 다릅니다). 객체가 어떻게 함수로 쓰이는지는객체 지향 프로그래밍을 할 때 알려드리겠습니다. parseInt, parseFloat과 다른점은 문자열에 문자가 들어있으면 처리하지 못하고 NaN이 됩니다.
숫자는 2진법, 8진법, 16진법을 표시할 수 있습니다. 2진법은 숫자 앞에 0b를, 8진법은 0을, 16진법은 0x를 붙이면 됩니다.
0b111; // 7
017; // 15
0xA3; // 163
이제 Math 객체에 대해 알아보겠습니다.
Math
각종 수학 계산을 도와줍니다. 이 객체는 Number과는 달리 Math()처럼 함수로는 사용할 수 없습니다.
Math.random()
예전에 보셨죠? 0부터 1 사이의 랜덤 값을 뽑아줍니다. 1은 불포함입니다.
Math.random(); // 0.xxxxxxxxx 매번 할 때마다 달라짐
Math.floor(값), Math.ceil(값), Math.round(값)
각각 숫자를 정수값으로 내림, 올림, 반올림합니다. 소수점을 반올림하려면 toFixed를 써야합니다.
Math.floor(5.5); // 5
Math.ceil(5.5); // 6
Math.round(5.5); // 6
Math.round(5.49); // 5
Math.abs(값)
절대값을 알려줍니다.
Math.abs(-15); // 15
Math.pow(값, 지수), Math.sqrt(값)
Math.pow는 거듭제곱이고, sqrt는 제곱근입니다.
Math.pow(2, 3); // 8
Math.sqrt(16); // 4
Math.max(값, 값, ...), Math.min(값, 값, ...)
Math.max(5, 6, 10); // 10
Math.min(2, 8, 9); // 2
여러 값들 중에 최대, 최소값을 찾아줍니다.
Math.PI
여러분을 학교 다닐 때 괴롭혔던 파이(π)입니다.
이외에도 Math 객체는 싸인, 코싸인, 탄젠트를 표시하는 것과 지수함수, 로그함수 등등 많은 것을 지원합니다. 저는 아직 써본 적은 없지만 3D 그래픽 작업, 게임 프로그래밍이나 물리학 관련 일을 하실 거면 필요하겠네요.
다음 시간은 배열에 대해서 알아보겠습니다.