Skip to content
This page has been auto-translated and may contain errors.View in English

숫자와 수학

docs.scrimba.com

장바구니는 가격을 더하고, 게임은 점수를 추적하고, 양식은 부과할 세금을 계산합니다. 결국 이 모든 것은 숫자와 그 숫자로 하는 산술 연산으로 귀결됩니다. 자바스크립트는 숫자를 핵심 구성 요소 중 하나로 다루며, 이 장에서는 숫자로 할 수 있는 것들을 다룹니다. 일상적인 계산, 반올림과 무작위성을 위한 내장 도우미, 그리고 거의 모든 사람이 걸려 넘어지는 부분인 페이지에 입력된 텍스트를 계산 가능한 숫자로 되돌리는 방법까지 살펴봅니다.

숫자와 산술 연산

자바스크립트에는 숫자 타입이 딱 하나뿐이고, 이것이 모든 것을 다룹니다. 42 같은 정수와 9.99 같은 소수는 똑같은 종류의 값이라서, 둘 중 하나를 골라야 할 일이 없습니다:

js
const price = 9.99;
const quantity = 3;
const total = price * quantity;
console.log(total); // 29.97

계산은 이미 알고 있는 기호로 합니다. +는 더하고, -는 빼고, *는 곱하고, /는 나눕니다. 하나 덜 익숙한 것이 있는데, %, 나머지 연산자입니다. 이것은 나누고 남은 값을 알려줍니다:

js
const remainder = 7 % 2;
console.log(remainder); // 1

7을 2로 나누면 3이 되고 1이 남으므로, 7 % 21입니다. 이 방법으로 숫자가 짝수인지 확인할 수 있습니다. 짝수를 2로 나누면 남는 것이 없으므로, 짝수는 number % 20, 홀수는 1이 됩니다.

자바스크립트는 정수와 소수를 구분하지 않고 하나의 숫자 타입으로 다루므로, 429.99는 같은 종류의 값입니다. 정수형과 부동소수점형을 따로 두는 언어들과는 다른 방식으로, 여기서는 어느 쪽을 의도하는지 선언할 필요가 없습니다.

산술 연산자는 +, -, *, /, % 다섯 가지입니다. 나머지 연산자 %는 나눈 후 남은 값을 반환하며, 초보자들이 생각하는 것보다 훨씬 쓸모가 많습니다:

js
const total = 17;
const perRow = 5;
const leftOver = total % perRow;
console.log(leftOver); // 2

17개 항목을 한 줄에 5개씩 배치하면 마지막 줄에는 2개가 남는데, 17 % 5가 바로 그 값을 알려줍니다. 가장 널리 쓰이는 용도는 짝수와 홀수 판별입니다. count % 2는 짝수면 0, 홀수면 1이 되는데, 이를 이용해 줄마다 색을 교대로 넣거나 목록을 반으로 나누기도 합니다.

연산자는 일반적인 수학의 우선순위를 따르므로, *, /, %+, -보다 먼저 계산되고, 우선순위가 같은 연산자끼리는 왼쪽에서 오른쪽으로 계산합니다. 순서가 중요할 때는 괄호를 쓰세요:

js
const withTax = (100 + 20) * 1.1;
console.log(withTax); // 132

자바스크립트에는 숫자 타입이 하나 있는데, 64비트 부동소수점 값입니다(IEEE 754 double, 대부분의 언어에서 double이라고 부르는 것과 같은 표현 방식입니다). 이 수준에서는 별도의 정수 타입이 없으므로, 42, 9.99, -3은 모두 같은 종류의 값이고, 여러분이 작성하는 모든 정수는 사실 소수 부분이 없을 뿐인 부동소수점 값입니다.

다섯 연산자는 + - * / %입니다. 나머지 연산자 %는 정확히 짚고 넘어가야 할 만한데, 이것이 나머지(remainder)이지 모듈로(modulo)가 아니기 때문입니다. 즉 왼쪽 피연산자의 부호를 따르므로, -7 % 31이 아니라 -2입니다. 일상적인 경우에는 그 값이 안정적이고 유용합니다. n % 2 === 0으로 짝수를 판별하는 것은 표준적인 방법이며, 음수에도 그대로 적용됩니다. -4 % 2도 여전히 0이니까요.

js
const total = 128;
const pageSize = 25;
const onLastPage = total % pageSize;
console.log(onLastPage); // 3

우선순위는 표준 수학 규칙을 따릅니다. *, /, %는 같은 등급으로 +, -보다 우선하고, 같은 등급 안에서는 왼쪽에서 오른쪽으로(좌결합) 계산됩니다. 비교 연산과 논리 연산까지 들어오면 전체 문법이 이보다 더 여러 층으로 나뉘는데, 이는 연산자에서 다룹니다. 산술 연산만 놓고 보면 필요한 규칙은 간단합니다. 곱셈·나눗셈류가 덧셈·뺄셈류보다 먼저이고, 읽는 사람이 멈춰서 생각해야 할 부분은 괄호로 묶으세요. 명확함이 문자 세 개를 아끼는 것보다 낫습니다.

js
const average = (a + b + c) / 3;
Juno숫자와 산술 연산 자바스크립트에는 숫자 타입이 하나뿐이라서 정수와 소수가 같은 것으로 취급되고, 둘 중 하나를 고를 필요가 없습니다. 연산자는 + - * /와 나눈 나머지를 구하는 %가 있습니다. 유용한 방법은 % 2인데, 짝수면 0, 홀수면 1이 됩니다.
Juno숫자와 산술 연산 숫자 타입이 하나뿐이라 정수와 소수를 다 다루므로, int인지 float인지 정할 필요가 없습니다. 다섯 연산자는 + - * /%이고, %는 기억해 둘 만합니다. count % 2는 짝수/홀수를 알려주고, 한 줄이 다 채워지지 않았을 때 몇 개가 남았는지도 알려줍니다. 우선순위는 일반 수학과 같으니, 읽는 사람이 생각해야 할 부분은 괄호로 묶으세요.
Juno숫자와 산술 연산 모든 숫자는 64비트 부동소수점이라서 별도의 정수 타입이 없고, 42도 소수 부분이 없는 double입니다. %에서 조심할 점은 이것이 나머지(remainder)이지 모듈로(modulo)가 아니라는 점입니다. 왼쪽 값의 부호를 따르므로 -7 % 3-2입니다. 짝수/홀수 판별에는 이 부분이 문제가 되지 않는데, n % 2 === 0은 음수에도 그대로 성립하기 때문입니다.

Math 객체

기본 연산자로는 부족할 때, 자바스크립트는 **Math**라는 내장 수학 도우미 모음을 제공합니다. 점(dot)을 붙여 이름으로 호출합니다:

js
console.log(Math.round(4.6)); // 5
console.log(Math.floor(4.6)); // 4
console.log(Math.ceil(4.1)); // 5

Math.round는 가장 가까운 정수로 반올림하고, Math.floor는 항상 내림하고, Math.ceil은 항상 올림합니다. 또 Math.maxMath.min도 있는데, 전달한 숫자들 중 가장 큰 값과 가장 작은 값을 골라줍니다:

js
console.log(Math.max(3, 8, 5)); // 8
console.log(Math.min(3, 8, 5)); // 3

그리고 Math.random은 0 이상 1 미만(1은 포함하지 않음)의 무작위 소수를 줍니다. 이것만으로는 원하는 결과를 얻기 어려운 경우가 많아서, 흔히 여기에 곱하고 내림을 해서 무작위 정수를 만듭니다:

js
const roll = Math.floor(Math.random() * 6) + 1;
console.log(roll); // 4 (매번 다른 숫자)

Math.random() * 6은 0 이상 6 미만의 값이 되고, Math.floor로 0부터 5까지의 정수로 만들고, + 1로 1부터 6까지의 주사위 값으로 바꿔줍니다.

**Math**는 수학 함수와 상수를 담고 있는 내장 객체입니다. 직접 만들 필요 없이 항상 존재하며, 점을 붙여 메서드를 호출합니다.

가장 자주 쓰는 것은 반올림 세 가지입니다:

js
console.log(Math.round(4.5)); // 5, 가장 가까운 정수
console.log(Math.floor(4.9)); // 4, 항상 내림
console.log(Math.ceil(4.1)); // 5, 항상 올림

Math.maxMath.min은 전달한 인수 중 가장 큰 값과 가장 작은 값을 반환하며, 값을 특정 범위 안으로 제한(clamp)할 때 편리합니다:

js
const clamped = Math.min(Math.max(userValue, 0), 100);
console.log(clamped); // 0과 100 사이로 유지됨

Math.random[0, 1) 범위의 소수를 반환합니다. 즉 0은 나올 수 있지만 1은 절대 나오지 않습니다. 이것을 0부터 n까지의 무작위 정수로 바꾸려면 Math.floor(Math.random() * n) 패턴을 씁니다:

js
const index = Math.floor(Math.random() * 5);
console.log(index); // 0부터 4까지의 정수

곱하면 범위가 [0, n)으로 넓어지고, 내림으로 소수 부분을 잘라내 정수로 만듭니다. 0부터 시작하지 않는 범위를 원할 때는 주사위 굴리기의 + 1처럼 오프셋을 더하세요.

**Math**는 정적(static) 네임스페이스 객체입니다. 인스턴스를 만드는 것이 아니라 수학 메서드와 상수를 담은 단순한 컨테이너입니다. 모든 메서드는 Math.something() 형태로 호출하며, 런타임에는 Math가 딱 하나만 존재합니다.

반올림 메서드들은 각각 서로 다른 방향으로 반올림합니다. Math.round는 가장 가까운 값으로(동점일 때는 위로 반올림해서, Math.round(2.5)3이지만 Math.round(-2.5)-2입니다), Math.floor는 음의 무한대 방향으로, Math.ceil은 양의 무한대 방향으로 반올림합니다. floor가 절삭(truncation)과 다르다는 점은 음수에서 중요한데, Math.floor(-1.2)-1이 아니라 -2입니다.

js
console.log(Math.floor(-1.2)); // -2, floor는 음수에서도 아래로 내려감

Math.maxMath.min은 인수를 몇 개든 받을 수 있어서, 값을 제한(clamp)하는 깔끔한 방법입니다:

js
const clamped = Math.min(Math.max(value, min), max);

Math.random[0, 1) 범위에서 균등하게 분포된 소수를 반환합니다. 무작위 정수를 만드는 관용구는 Math.floor(Math.random() * range) + start입니다. 범위 너비만큼 곱하고, 내림으로 정수를 만들고, 시작값만큼 이동시킵니다. 주의할 점이 둘 있습니다. 암호학적으로 안전하지 않으므로 토큰이나 사용자가 추측하면 안 되는 값에는 절대 쓰지 마세요(그럴 때는 crypto.getRandomValues가 있습니다). 그리고 포함/제외 경계를 혼동해서 발생하는 off-by-one 버그가 흔하니, 상한값이 나올 수 있는지 미리 정해두세요.

js
const dice = Math.floor(Math.random() * 6) + 1;
console.log(dice); // 1부터 6까지 포함
JunoMath 객체Math는 점을 붙여 호출하는 미리 만들어진 수학 도구 상자입니다. Math.round, Math.floor(내림), Math.ceil(올림), 그리고 가장 큰 값과 작은 값을 구하는 Math.max / Math.min이 있습니다. Math.random은 0부터 1 사이의 소수를 주는데, 외워둘 만한 방법은 무작위 정수를 만드는 Math.floor(Math.random() * n)입니다. 저도 이 패턴을 믿기까지 몇 번 시도해봤으니, 그대로 따라 적어보고 천천히 읽어보세요.
JunoMath 객체Math는 별도 설정 없이 항상 존재하며, 점을 붙여 메서드를 호출합니다. 반올림 세 가지를 기억하세요. round는 가장 가까운 값, floor는 내림, ceil은 올림입니다. minmax를 함께 쓰면 값을 특정 범위로 제한할 수 있습니다. 무작위 값이 필요하면 Math.floor(Math.random() * n)이 0부터 n까지의 정수를 주고, 오프셋을 더하면 범위를 옮길 수 있습니다.
JunoMath 객체Math는 정적 네임스페이스라서 딱 하나만 존재하고 생성할 필요가 없습니다. 음수에서 반올림 방향에 주의하세요. Math.floor(-1.2)-2이고 이는 절삭이 아니며, Math.round는 동점일 때 위쪽으로 반올림합니다. Math.floor(Math.random() * range) + start가 정수 관용구지만, Math.random은 안전하지 않으므로 사용자가 추측하면 안 되는 값에는 crypto.getRandomValues를 쓰세요.

문자열을 숫자로 바꾸기

사람이 페이지에 입력하는 것은 숫자처럼 보여도 항상 **텍스트**로 들어옵니다. 입력창에 5를 입력하면 숫자 5가 아니라 문자열 "5"를 얻습니다. 이것이 중요한 이유는, +가 문자열 두 개에 적용되면 더하는 게 아니라 이어 붙이기 때문입니다:

js
const a = "5";
const b = "3";
console.log(a + b); // "53", 8이 아님

계산을 하려면 먼저 텍스트를 숫자로 변환해야 합니다. 가장 명확한 방법은 Number()입니다:

js
const count = Number("5");
console.log(count + 3); // 8

그 외에도 두 가지가 있습니다. parseInt는 정수를 읽고 소수 부분을 버리고, parseFloat는 소수 부분을 유지합니다:

js
console.log(parseInt("42px")); // 42
console.log(parseFloat("9.99")); // 9.99

이 둘은 "42px"처럼 어떤 텍스트의 앞쪽에 놓인 숫자를 읽을 수 있는데, Number는 이를 하지 못합니다. 문자열 앞에 +를 붙이는 지름길도 있는데, Number와 같은 방식으로 변환합니다:

js
console.log(+"7"); // 7

페이지에서 오는 입력은 항상 **문자열**입니다. 폼 필드, URL, data 속성 모두 텍스트이고, "5"도 마찬가지입니다. +가 문자열을 이어 붙이기 때문에, 두 텍스트 값을 더하면 합산되는 게 아니라 이어 붙여지는데, 이것이 초보자들이 가장 많이 겪는 숫자 관련 버그입니다:

js
const price = "10";
const shipping = "5";
console.log(price + shipping); // "105", 문자열 이어 붙이기

계산 전에 변환하세요. Number()는 엄격하고 읽기 쉬운 선택입니다. 깨끗한 숫자 문자열이면 숫자로 바꾸고, 완전히 숫자가 아닌 값에는 NaN을 줍니다.

js
console.log(Number("42")); // 42
console.log(Number("42px")); // NaN, 완전한 숫자가 아님

parseIntparseFloat는 더 관대합니다. 문자열 앞쪽부터 숫자를 읽다가 맞지 않는 첫 문자에서 멈추는데, 그래서 parseInt("42px")42입니다. parseInt는 소수 부분을 버리고, parseFloat는 유지합니다:

js
console.log(parseInt("42px", 10)); // 42
console.log(parseFloat("3.14 radians")); // 3.14

parseInt에는 두 번째 인수로 10을 넘겨서 항상 10진수로 읽게 하세요. 단항 연산자 +Number와 똑같이 동작하는 간결한 변환기입니다. 값 전체가 숫자여야 할 때는 Number()를, 텍스트 안에 숫자가 섞여 있을 때는 parseInt/parseFloat를 쓰세요.

외부에서 들어오는 텍스트는 항상 **문자열**이고, +가 이어 붙이기용으로 오버로드되어 있어서 "10" + "5""105"가 됩니다. +를 제외한 모든 산술 연산자는 피연산자를 숫자로 강제 변환하므로 "10" * 110이 되지만, 이 동작에 의존하는 것은 가독성 측면에서 함정입니다. 의도적으로 변환하세요.

Number()는 문자열 전체를 강제 변환합니다. 트리밍된 문자열 전체가 유효한 숫자 리터럴일 때만 성공하고, 그렇지 않으면 NaN입니다. 16진수(Number("0x1f")31)와 지수 표기, 앞뒤 공백을 이해하며, ""0으로 취급하는데 이는 알아둘 만한 날카로운 함정입니다.

js
console.log(Number("")); // 0, 놓치기 쉬운 함정
console.log(Number("  12 ")); // 12, 공백이 트리밍됨
console.log(Number("12abc")); // NaN

parseIntparseFloat는 접두부만 파싱합니다. 읽을 수 있는 만큼 읽고 나머지는 무시하므로, parseInt("12abc")12입니다. parseInt에는 항상 진법을 지정하세요(parseInt(str, 10)). 지정하지 않으면 "0x10" 같은 입력이 16진수로 읽힙니다. 단항 연산자 +Number 강제 변환의 가장 짧은 형태로 간결한 코드에서 자주 보이며(+"3.5"3.5), 규칙도 같고 ""0이 되는 함정도 똑같이 있습니다.

실전에서 쓸 규칙은 이렇습니다. 값 전체가 숫자여야 하고 그렇지 않으면 오류로 잡아내고 싶을 때는 Number(또는 +)를, 예상한 텍스트 안에 숫자가 섞여 있을 때는 parseInt/parseFloat를 씁니다. 어느 쪽을 고르든 결과가 NaN이 될 수 있는데, 이는 다음 절에서 다룹니다. 비교와 강제 변환에 대한 더 자세한 내용은 연산자에, 문자열 쪽 이야기는 문자열에 있습니다.

Juno문자열을 숫자로 바꾸기 페이지에 입력하는 것은 무엇이든 텍스트라서, "5"는 숫자 5가 아니고, "5" + "3"8이 아니라 "53"이 됩니다. 먼저 변환하세요. Number("5")가 가장 명확하고, parseInt는 정수를 읽고, parseFloat는 소수를 유지하며, 문자열 앞에 붙이는 +는 빠른 지름길입니다. 더하는 대신 이어 붙는 함정을 조심하세요. 누구나 한 번은 걸립니다.
Juno문자열을 숫자로 바꾸기 페이지 입력은 항상 문자열이고, +가 문자열을 이어 붙이므로 "10" + "5""105"가 되는데, 이것이 가장 흔한 숫자 관련 버그입니다. 값 전체가 숫자여야 할 때는 Number()를 쓰고, "42px"처럼 텍스트 안에 숫자가 섞여 있을 때는 parseIntparseFloat를 쓰세요. parseInt에 10진수 인수를 넘기면 예상치 못한 결과를 피할 수 있습니다.
Juno문자열을 숫자로 바꾸기+를 제외한 모든 연산자는 숫자로 강제 변환하므로 "10" * 1도 동작하지만, 그래도 의도적으로 변환하는 것이 좋습니다. Number()는 문자열 전체가 숫자여야 하고 ""는 조용히 0이 되며, parseIntparseFloat는 접두부만 파싱하고 나머지는 무시하므로 parseInt에는 항상 진법 10을 넘기세요. 이 중 무엇이든 NaN을 내놓을 수 있는데, 이는 다음으로 익숙해져야 할 내용입니다.

숫자의 날카로운 함정들

자바스크립트의 숫자에는 한 번쯄 미리 봐두면 좋은 놀라운 점이 있습니다. 단순한 소수 두 개를 더하면 이상한 답이 나올 수 있습니다:

js
console.log(0.1 + 0.2); // 0.30000000000000004

이건 코드의 버그가 아닙니다. 컴퓨터는 모든 소수를 정확히 표현할 수 없는 방식으로 저장하기 때문에, 아주 작은 오차가 스며듭니다. 대부분의 경우 문제가 되지 않고, 문제가 될 때는 표시하기 전에 결과를 반올림합니다:

js
const sum = 0.1 + 0.2;
console.log(Math.round(sum * 100) / 100); // 0.3

NaN이라는 값도 만나게 될 텐데, "숫자가 아님(not a number)"이라는 뜻입니다. 말이 안 되는 텍스트를 숫자로 바꾸려는 것처럼, 계산에 합리적인 답이 없을 때 이 값이 나옵니다:

js
console.log(Number("hello")); // NaN

출력에 NaN이 보인다면 대개 어딘가에서 변환이 잘못됐다는 뜻이니, 두려워할 것이 아니라 유용한 힌트로 여기세요.

숫자 값 두 가지는 언젠가는 여러분을 놀라게 할 텐데, 미리 알아두고 만나는 게 좋습니다.

첫 번째는 부동소수점(floating-point) 부정확성입니다. 소수는 이진법으로 저장되기 때문에 일부 값은 정확히 표현할 수 없어서, 0.1 + 0.2는 정확히 0.3이 아닙니다:

js
console.log(0.1 + 0.2 === 0.3); // false

실전에서 쓰는 해결책은 표시할 때 반올림하거나, 아예 정수 단위로 다루는 것입니다. 금액이 대표적인 예입니다. 금액을 정수 센트 단위로 보관하고(10.99가 아니라 1099), 화면에 보여줄 때만 나누면 이 오차를 완전히 피할 수 있습니다.

js
const cents = 1099;
console.log(cents / 100); // 10.99, 표시할 때는 정확함

두 번째는 NaN, "숫자가 아님"이며, Number("hello")0 / 0처럼 숫자로 답이 나올 수 없는 연산의 결과입니다. 가장 이상한 특성은 자기 자신과도 같지 않다는 점입니다:

js
console.log(NaN === NaN); // false

그래서 ===로는 검사할 수 없습니다. 대신 NaN일 때만 true를 반환하는 Number.isNaN(value)를 쓰세요:

js
console.log(Number.isNaN(Number("hello"))); // true

Infinity도 있는데, 0으로 나누거나(1 / 0) 숫자 범위를 넘어설 때 나오는 값입니다. 비교에서는 실제 값처럼 동작하지만, 계산이 한계를 넘어섰다는 신호이기도 합니다.

숫자 타입의 경계에는 세 가지 값이 있고, 전문가라면 이 세 가지를 반사적으로 알아둘 필요가 있습니다.

부동소수점(floating-point) 부정확성이 가장 유명합니다. IEEE 754는 숫자를 이진법으로 저장하는데, 0.1 같은 값은 이진수로 정확히 표현할 수 없어서 산술 연산에서 반올림 오차가 누적됩니다:

js
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false

양쪽 중 어느 하나라도 산술 연산에서 나온 값이라면 부동소수점을 ===로 비교하지 마세요. 실전에서 통하는 해결책은 두 가지입니다. 표시하거나 비교할 때 고정된 정밀도로 반올림하는 것, 또는 화폐처럼 정확성이 요구되는 경우라면 가장 작은 정수 단위로 다루고 경계에서만 변환하는 것입니다. 금액을 정수 센트(1099)로 저장하고 출력할 때만 서식을 입히면, 버그 한 건을 고치는 게 아니라 그 부류 전체를 없앨 수 있습니다.

js
const totalCents = 1099 + 250;
console.log(totalCents); // 1349, 정확한 정수 연산

NaN은 숫자 타입의 오류 값으로, 0 / 0, Number("x"), 그리고 수치적으로 정의되지 않은 결과를 내는 모든 연산에서 나옵니다. 명세에 규정된 독특한 특성이 있는데, 자기 자신과 같지 않은 유일한 값이라는 점입니다. 그래서 NaN === NaNfalse입니다. 이 때문에 항등 검사가 실패하고, 그래서 신뢰할 수 있는 검사법인 Number.isNaN(x)가 존재합니다. 예전부터 있던 전역 isNaN보다는 Number.isNaN 형태를 쓰세요. isNaN은 인수를 먼저 강제 변환하기 때문에 실제로는 NaN이 아닌 "hello" 같은 것도 true로 보고합니다.

js
console.log(NaN === NaN); // false, NaN은 자기 자신과도 같지 않음
console.log(Number.isNaN(0 / 0)); // true, 신뢰할 수 있는 검사법

Infinity(그리고 -Infinity)는 1 / 0이나 표현 가능한 범위를 넘어섰을 때 나오는 값입니다. 실제로 비교 가능한 값이라서(Infinity > 1e308true), 최솟값을 찾을 때 "아직 한계 없음"을 나타내는 편리한 표지로 쓸 수 있지만, 화면이나 데이터베이스까지 도달하면 놀라운 일이 됩니다. 결과가 오버플로되거나 0으로 나눠질 수 있는 경우라면, Infinity가 아래쪽으로 흘러가기 전에 합리적인 대체값을 미리 정해두세요.

Juno숫자의 날카로운 함정들 소수는 조금 느슨하게 저장되기 때문에, 0.1 + 0.20.30000000000000004로 나오는데, 이는 정상이고 코드의 버그가 아닙니다. 문제가 될 때는 보여주기 전에 결과를 반올림하세요. 그리고 NaN은 "숫자가 아님"을 뜻하는, 변환이 실패했을 때 나오는 답이니, 어떤 텍스트가 예상대로 숫자로 바뀌지 않았다는 힌트로 받아들이세요.
Juno숫자의 날카로운 함정들 부동소수점 때문에 0.1 + 0.2는 정확히 0.3이 아니므로, 표시할 때 반올림하거나 금액처럼 정수 센트 단위로 다루세요. NaN은 "숫자로 나올 답이 없음"을 뜻하는 값이고, NaN === NaNfalse라는 함정이 있으니 대신 Number.isNaN으로 검사하세요. Infinity는 0으로 나눌 때 나타나며 계산이 한계를 넘어섰다는 뜻입니다.
Juno숫자의 날카로운 함정들 산술 연산에서 나온 부동소수점을 ===로 비교하지 마세요. 정밀도로 반올림하거나 금액을 정수 센트로 다루면 이 오차 자체가 사라집니다. NaN은 자기 자신과 같지 않은 유일한 값이고, 바로 이 때문에 Number.isNaN이 존재하니 강제 변환을 하는 전역 isNaN 대신 이것을 쓰세요. Infinity는 0으로 나누거나 오버플로에서 나오는 실제 비교 가능한 값이므로, 화면이나 데이터베이스에 도달하기 전에 합리적인 대체값을 마련해두세요.

숫자 다음으로 알아볼 것

숫자는 자바스크립트의 핵심 데이터 타입 몇 가지 중 하나로, 텍스트나 참/거짓 값과 나란히 자리합니다. 실제 프로그램은 대부분 이들을 섞어 쓰는데, 문자열에서 숫자를 뽑아내고, 그것을 비교하고, 결과를 변수에 저장하는 식입니다. 이런 비교와 결합을 담당하는 연산자에 대해서는 다음 글인 연산자에서 다룹니다.