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

숫자와 수학

docs.scrimba.com

쇼핑 카트는 가격을 더하고, 게임은 점수를 추적하고, 폼은 얼마나 많은 세금을 부과할지 계산합니다. 이 모든 것은 숫자와 그것들을 사용한 산술로 귀결됩니다. JavaScript는 숫자를 핵심 구성 요소 중 하나로 취급하며, 이 장에서는 숫자로 할 수 있는 것들을 다룹니다: 일상적인 수학, 반올림과 무작위성을 위한 기본 제공 도우미, 그리고 거의 모든 사람을 곤란하게 하는 부분인 페이지에 입력된 텍스트를 더할 수 있는 숫자로 변환하는 것입니다.

숫자와 산술

JavaScript는 하나의 number 타입을 가지고 있으며, 모든 것을 포함합니다. 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 % 2는 짝수의 경우 0이고 홀수의 경우 1입니다.

JavaScript는 정수와 소수 모두를 위한 단일 number 타입을 가지고 있으므로, 429.99는 같은 종류의 값입니다. 이것은 정수와 부동소수점을 별도의 타입으로 분할하는 언어들과 다릅니다; 여기서는 어떤 것을 의도하는지 선언할 필요가 없습니다.

5개의 산술 연산자는 +, -, *, /, %입니다. 나머지 연산자 %는 나눈 후 남은 것을 반환하며, 초보자가 예상하는 것보다 더 유용합니다:

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

JavaScript는 하나의 number 타입, 64비트 부동소수점 값(IEEE 754 double, 대부분의 언어가 double이라고 부르는 것과 같은 표현)을 가지고 있습니다. 이 수준에서는 별도의 정수 타입이 없으므로, 42, 9.99, -3은 모두 같은 종류의 것이며, 작성하는 모든 정수는 정말로 소수 부분이 없는 부동소수점입니다.

5개의 연산자는 + - * / %입니다. 나머지 %는 핵심을 짚고 넘어갈 만한 가치가 있습니다. 왜냐하면 modulo가 아니라 remainder이기 때문입니다: 왼쪽 피연산자의 부호를 취하므로, -7 % 31이 아니라 -2입니다. 일상적인 경우 그 값은 안정적이고 유용합니다. 짝수 테스트인 n % 2 === 0은 정규 트릭이며, -4 % 2가 여전히 0이므로 음수에도 유지됩니다.

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

우선순위는 표준 수학을 따릅니다: *, /, %+- 위에 있는 티어를 공유하며, 티어 내에서 평가는 왼쪽에서 오른쪽으로(왼쪽 결합) 수행됩니다. 비교와 논리가 들어오면 전체 문법이 더 계층적이며, 이는 operators의 주제입니다. 산술만 해당하면 필요한 규칙은 간단합니다: 승법을 덧셈 전에, 독자가 멈추고 생각해야 할 것들에는 괄호를 사용하십시오. 명확함이 3글자 절약을 이깁니다.

js
const average = (a + b + c) / 3;
Juno숫자와 산술 JavaScript에는 하나의 number 타입이 있으므로 정수와 소수는 같은 것이며 그들 사이에서 선택할 필요가 없습니다. 연산자는 + - * /와 나머지인 %입니다. 나누면 남은 것을 줍니다. 편리한 트릭은 % 2입니다: 짝수는 0이고 홀수는 1입니다.
Juno숫자와 산술 하나의 number 타입이 정수와 소수를 모두 포함하므로 int 대 float 결정을 할 필요가 없습니다. 5개의 연산자는 + - * /%이며, %는 기억할 만한 가치가 있습니다: count % 2는 짝수 또는 홀수를 제공하며, 부분적으로 채워진 행에 남은 것을 알려줍니다. 우선순위는 일반적인 수학이므로 독자가 생각해야 할 것들에는 괄호를 사용하십시오.
Juno숫자와 산술 모든 숫자는 64비트 부동소수점이므로 별도의 정수 타입이 없으며 42는 분수가 없는 double입니다. %의 유일한 주의 사항은 modulo가 아니라 remainder이므로 왼쪽 부호를 취하며 -7 % 3-2입니다. 짝수 또는 홀수 테스트의 경우 n % 2 === 0은 음수에도 유지되므로 절대 물지 않습니다.

Math 객체

기본 연산자보다 더 필요할 때, JavaScript는 **Math**를 제공하며, 이는 수학 도우미의 기본 제공 컬렉션입니다. 점으로 이름을 호출합니다:

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까지의 무작위 소수를 줍니다. 자체로는 원하는 것이 거의 없으므로 일반적인 패턴은 이를 곱하고 정수를 얻기 위해 floor합니다:

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**는 수학 함수와 상수를 포함하는 기본 제공 객체입니다. 이를 생성하지 않습니다; 항상 존재하며, 점으로 메서드를 호출합니다.

반올림 3개 조합이 가장 자주 사용합니다:

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은 인수 중 가장 크고 가장 작은 것을 반환하며, 값을 범위로 제한하는 데 편리합니다:

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)로 펼치고, floor는 소수를 자르므로 정수에 도달합니다. 0에서 시작하지 않는 범위를 원할 때는 오프셋을 추가합니다. 예를 들어, 주사위 굴림을 위해 + 1을 추가합니다.

**Math**는 정적 네임스페이스 객체입니다: 수학 메서드와 상수의 일반 컨테이너이며, 인스턴스화할 것이 아닙니다. 모든 메서드는 Math.something()으로 호출되며, 런타임에는 정확히 하나의 Math가 있습니다.

반올림 메서드는 각각 다른 목표를 향해 반올림합니다: Math.round는 가장 가까운 것으로(동점은 올림이므로, Math.round(2.5)3이지만 Math.round(-2.5)-2), Math.floor는 음의 무한대를 향해, Math.ceil은 양의 무한대를 향해. floor가 절단이 아니라는 구분은 음수의 경우 중요하며, Math.floor(-1.2)-1이 아니라 -2입니다.

js
console.log(Math.floor(-1.2)); // -2, floor는 음수에서도 내림

Math.maxMath.min은 임의의 인수 개수를 취하며 제한하는 깔끔한 방법입니다:

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

Math.random[0, 1)에서 균등하게 분포된 부동소수점을 반환합니다. 무작위 정수의 관용구는 Math.floor(Math.random() * range) + start입니다: 범위 너비로 스케일, 정수로 floor, 시작 값으로 이동합니다. 주의할 두 가지가 있습니다: 암호화 보안이 아니므로 토큰이나 사용자가 추측할 수 없어야 하는 것에는 절대 사용하지 마십시오(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는 항상 존재하며, 설정이 필요하지 않으며, 점으로 메서드를 호출합니다. 반올림 3개 조합을 직선으로 유지하십시오: 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를 사용하십시오.

문자열을 숫자로 변환하기

페이지에 입력한 모든 것은 숫자처럼 보이더라도 **text**로 도착합니다. 상자에 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

페이지의 입력은 항상 **string**입니다. 폼 필드, URL, 데이터 속성: 모두 텍스트이며, "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를 사용하십시오.

외부 세계의 텍스트는 항상 **string**이며, +가 연결을 위해 오버로드되기 때문에 "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 (또는 +), 숫자가 "42px"와 같이 기대하는 텍스트에 포함되어 있을 때 parseInt/parseFloat. 어떤 것을 선택하든, 결과는 NaN일 수 있으며, 다음 섹션이 이것에 관한 것입니다. 이것 너머의 비교와 강제 변환은 operators에 있으며, 문자열 쪽의 이야기는 strings에 있습니다.

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을 제공할 수 있으며, 이는 다음에 편해져야 할 일입니다.

숫자의 날카로운 모서리

JavaScript의 숫자는 초기에 한 번 볼 가치가 있는 놀라움을 담고 있습니다. 두 개의 간단한 소수를 더하면 이상한 답을 얻을 수 있습니다:

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을 보는 것은 보통 변환이 어딘가 잘못되었다는 의미이므로, 두려워해야 할 것보다는 유용한 단서입니다.

두 개의 숫자 값이 결국 놀라게 할 것이며, 의도적으로 그들을 만나는 것이 더 낫습니다.

첫 번째는 부동소수점 부정확성입니다. 소수는 이진수로 저장되기 때문에, 일부 값은 정확히 유지될 수 없으므로, 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입니다. "not a number"이며, Number("hello")0 / 0과 같이 숫자 답이 없는 연산의 결과입니다. 가장 이상한 특성은 자신과 같지 않다는 것입니다:

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

따라서 ===로 테스트할 수 없습니다. Number.isNaN(value)를 사용하십시오. 이는 NaN에 대해서만 true를 반환합니다:

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

또한 Infinity가 있습니다. 0으로 나누거나(1 / 0) 숫자 범위를 초과할 때 얻는 것입니다. 비교에서 실제 값처럼 작동하지만 계산이 모서리를 벗어났음을 신호합니다.

세 개의 값이 숫자 타입의 모서리에 앉아 있으며, 전문가는 이 세 가지 모두를 반사적인 메모리에 필요로 합니다.

부동소수점 부정확성은 유명한 것입니다. 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 형태를 선호하십시오. 이는 먼저 인수를 강제 변환하므로 실제로 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은 "not a number"를 의미하며, 변환이 실패했을 때 얻는 답이므로 텍스트가 기대한 대로 숫자로 변환되지 않았다는 단서로 취급합니다.
Juno숫자의 날카로운 모서리 부동소수점은 0.1 + 0.2가 정확히 0.3이 아니므로, 표시를 위해 반올림하거나 돈의 경우 정수 센트와 같은 전체 단위로 작업합니다. NaN은 "no numeric answer" 값이며, 그 함정은 NaN === NaNfalse이므로 대신 Number.isNaN으로 테스트하는 것입니다. Infinity는 0으로 나누기에서 나타나며 계산이 모서리를 벗어났음을 의미합니다.
Juno숫자의 날카로운 모서리 산술 부동소수점을 절대 ===로 비교하지 마십시오; 정밀도로 반올림하거나 정수 센트에 돈을 유지하므로 오류 클래스가 사라집니다. NaN은 유일하게 자신과 같지 않은 값이며, 이는 정확히 Number.isNaN이 존재하는 이유이고, 강제 변환하는 전역 isNaN보다는 이를 사용하십시오. Infinity는 0으로 나누기나 오버플로우에서 나온 실제 비교 가능한 값이므로 표시나 데이터베이스에 도달하기 전에 건전한 폴백을 제공하십시오.

숫자가 다음으로 가는 곳

숫자는 JavaScript의 몇 가지 핵심 data types 중 하나이며, 텍스트 및 true/false 값 옆에 앉아 있습니다. 대부분의 실제 프로그램은 이들을 혼합하여 문자열에서 숫자를 뽑고, 이를 비교하고, 결과를 variable에 저장하며, 그 비교와 결합을 하는 연산자는 다음의 operators의 주제입니다.