Math` 객체
이 글은 Math 객체에 대해 설명합니다.
기본 사용법부터 일반적인 실무 패턴, 그리고 주의해야 할 점과 대처 방법까지 단계적으로 설명합니다.
YouTube Video
Math` 객체
자바스크립트의 Math 객체는 수치 계산을 위한 내장 유틸리티를 제공합니다.
상수
Math에 정의된 상수는 고정밀 값 취급에 유용합니다.
다음 코드는 몇 가지 대표적인 상수들을 보여줍니다.
1// Show common Math constants
2console.log("Math.PI:", Math.PI); // 3.141592653589793
3console.log("Math.E:", Math.E); // Euler's number
4console.log("Math.LN2:", Math.LN2); // Natural log of 2
5console.log("Math.SQRT2:", Math.SQRT2); // Square root of 2
- 이러한 상수들은 삼각 함수, 로그 변환, 정규화 등에서 그대로 사용할 수 있습니다. 예를 들어
Math.PI는 각도를 라디안으로 변환할 때 필요합니다.
기본 반올림과 절댓값(abs, floor, ceil, round, trunc)
반올림과 부호 처리는 자주 사용되므로, Math.floor, Math.ceil, Math.round의 차이를 제대로 이해하는 것이 중요합니다. 특히 음수 처리 시 결과가 직관과 다를 수 있으니, 각 반올림 규칙의 작동 방식을 주의 깊게 이해하고 적절히 사용해야 합니다.
다음 예시들은 반올림 함수들 간의 차이를 나타냅니다.
1// Examples of rounding and absolute value functions
2const pos = 3.7;
3const neg = -3.7;
4
5// --- floor ---
6console.log("Math.floor(3.7):", Math.floor(pos)); // 3
7console.log("Math.floor(-3.7):", Math.floor(neg)); // -4
8// (rounds toward smaller value)
9
10// --- ceil ---
11console.log("Math.ceil(3.7):", Math.ceil(pos)); // 4
12console.log("Math.ceil(-3.7):", Math.ceil(neg)); // -3
13// (rounds toward larger value)
14
15// --- round ---
16console.log("Math.round(3.5):", Math.round(3.5)); // 4
17// (.5 goes up for positive numbers)
18console.log("Math.round(-3.5):", Math.round(-3.5)); // -3
19// (.5 moves toward zero for negative numbers)
20
21// --- trunc ---
22console.log("Math.trunc(3.7):", Math.trunc(pos)); // 3
23console.log("Math.trunc(-3.7):", Math.trunc(neg)); // -3
24// (fraction removed toward zero)
25
26// --- abs ---
27console.log("Math.abs(-3.7):", Math.abs(neg)); // 3.7
Math.floor는 음수에 대해 더 작은 방향으로 반올림하므로-3.7은-4가 됩니다.Math.ceil은 음수에 대해 더 큰 방향으로 반올림하므로-3.7은-3이 됩니다.Math.round는 양수에서는 .5 이상을 올림, 음수에서는 0에 가깝게 반올림합니다.- 음수의 경우 결과가 직관과 다를 수 있으니, 어느 방향으로 반올림되는지 명확히 이해하는 것이 중요합니다.
- 반올림 함수는 용도에 따라 선택해야 합니다. 예를 들어, 인덱스 계산에는
Math.floor, 상한값에는Math.ceil, 소수점 이하를 단순히 버릴 때에는Math.trunc를 사용합니다.
곱셈, 제곱/제곱근(pow, **, sqrt, cbrt, hypot)
거듭제곱과 제곱근은 Math.pow 또는 ** 연산자를 사용하여 계산할 수 있습니다. Math.hypot는 제곱합의 제곱근(거리)를 안전하게 계산합니다.
아래는 거듭제곱 및 hypot 예제입니다. Math.hypot는 오버플로우와 언더플로우의 영향을 줄여줍니다.
1// Power, root and hypot examples
2console.log("2 ** 10:", 2 ** 10); // 1024
3console.log("Math.pow(2, 10):", Math.pow(2, 10));// 1024
4console.log("Math.sqrt(16):", Math.sqrt(16)); // 4
5console.log("Math.cbrt(27):", Math.cbrt(27)); // 3
6console.log("Math.hypot(3, 4):", Math.hypot(3, 4));// 5 (3-4-5 triangle)
Math.hypot는 삼각형 변이나 다차원 벡터의 길이를 구할 때 유용합니다.
지수 및 로그 함수(exp, log, log10, log2)
지수와 로그는 확률, 지수 감쇠, 스케일링에서 자주 사용됩니다.
다음은 exp 및 로그 함수의 기본 예제입니다. 로그의 밑수에 따라 적합한 함수를 선택하세요.
1// Exponential and logarithm examples
2console.log("Math.exp(1):", Math.exp(1)); // e^1
3console.log("Math.log(Math.E):", Math.log(Math.E)); // natural log, 1
4console.log("Math.log10(100):", Math.log10(100)); // 2
5console.log("Math.log2(8):", Math.log2(8)); // 3
- 자연로그(
Math.log)는 통계 및 미분방정식에서 표준적으로 사용됩니다. 상용로그나 밑 2의 로그도 용도에 따라 선택합니다.
삼각 함수(sin, cos, tan, asin, acos, atan2)
삼각 함수는 각도 계산, 회전, 좌표 변환에서 필수입니다. Math.atan2(y, x)는 사분면을 고려한 정확한 각도 계산에 유용합니다.
atan2의 기본 예제 및 사용법은 아래와 같습니다. 각도는 라디안 단위로 처리해야 합니다.
1// Trigonometry examples (angles in radians)
2const degToRad = deg => deg * (Math.PI / 180);
3const radToDeg = rad => rad * (180 / Math.PI);
4
5console.log("Math.sin(PI/2):", Math.sin(Math.PI / 2)); // 1
6console.log("Math.cos(0):", Math.cos(0)); // 1
7console.log("Math.tan(Math.PI / 4):", Math.tan(Math.PI / 4)); // ~1
8
9// Using atan2 to compute angle of vector (x, y)
10const x = -1, y = 1;
11const angle = Math.atan2(y, x); // returns angle in radians taking quadrant into account
12console.log("atan2(1, -1) in degrees:", radToDeg(angle)); // 135
atan2는 벡터의 각도를 안전하게 구할 수 있어 회전이나 방향 계산에 적합합니다.
난수 생성(Math.random 및 실용 패턴)
Math.random()은 [0, 1) 범위의 균등 분포 난수를 반환합니다. 필요에 따라 정수 범위나 정규 분포로 변환하거나 확장할 수 있습니다.
다음은 난수 유틸리티 함수 예제입니다. 암호학적으로 안전한 난수가 필요하다면, crypto.getRandomValues를 사용하세요.
1// Random utilities using Math.random
2
3// Get integer in [min, max] inclusive
4function randomInt(min, max) {
5 // Returns integer between min and max (inclusive)
6 return Math.floor(Math.random() * (max - min + 1)) + min;
7}
8console.log("randomInt(1, 6):", randomInt(1, 6)); // dice roll example
9
10// Get float in [min, max)
11function randomFloat(min, max) {
12 return Math.random() * (max - min) + min;
13}
14console.log("randomFloat(0, 5):", randomFloat(0, 5));
15
16// Fisher-Yates shuffle
17function shuffle(array) {
18 for (let i = array.length - 1; i > 0; i--) {
19 const j = Math.floor(Math.random() * (i + 1));
20 // swap array[i] and array[j]
21 [array[i], array[j]] = [array[j], array[i]];
22 }
23 return array;
24}
25console.log("shuffle([1,2,3,4,5]):", shuffle([1,2,3,4,5]));Math.random은 일반적인 용도에는 편리하지만, 게임 재생이나 암호화 등에서는 재현성 또는 보안성에 대한 대책이 필요합니다.
실용적 도우미 함수들(clamp, lerp, mapRange, 각도 정규화)
자주 쓰이는 수학적 작업에 직접 소형 유틸리티 함수를 작성하는 것이 도움이 됩니다.
자주 사용되는 유틸리티 구현 예시는 다음과 같습니다.
1// Utility functions: clamp, lerp, mapRange, normalizeAngle
2
3// Clamp value between min and max
4function clamp(v, min, max) {
5 return Math.max(min, Math.min(max, v));
6}
7console.log("clamp(10, 0, 5):", clamp(10, 0, 5)); // 5
8
9// Linear interpolation: t in [0,1]
10function lerp(a, b, t) {
11 return a + (b - a) * t;
12}
13console.log("lerp(0, 10, 0.25):", lerp(0, 10, 0.25)); // 2.5
14
15// Map value from one range to another
16function mapRange(v, inMin, inMax, outMin, outMax) {
17 const t = (v - inMin) / (inMax - inMin);
18 return lerp(outMin, outMax, t);
19}
20console.log("mapRange(5, 0, 10, 0, 100):", mapRange(5, 0, 10, 0, 100));
21// -> 50
22
23// Normalize angle to [-PI, PI)
24function normalizeAngle(rad) {
25 return Math.atan2(Math.sin(rad), Math.cos(rad));
26}
27console.log("normalizeAngle(3*PI):", normalizeAngle(3 * Math.PI));- 이 코드는 값 제한, 보간, 구간 매핑, 각도 정규화 등 수치 연산에 자주 쓰이는 소형 유틸리티 함수들을 모아놓은 것입니다.
clamp는 값을 지정 범위로 제한하고,lerp,mapRange는 자연스러운 보간이나 구간 변환을 수행합니다. 또한normalizeAngle은 각도를 항상[-π, π)범위로 정규화하여 회전 계산의 안정성을 높여줍니다. - 이러한 도우미 함수들은 그래픽, 게임, 상호작용 프로그래밍에서 자주 사용됩니다.
normalizeAngle은 각도 차이 비교나 보간 계산에 중요합니다.
부동소수점 및 반올림 주의점(정밀도와 비교)
자바스크립트 숫자는 IEEE-754 더블 프리시전 부동소수점(64비트)이므로, 비교나 반올림 시 주의가 필요합니다. 예시로, 0.1 + 0.2 !== 0.3 이 됩니다.
다음은 반올림 오차 처리 예시입니다. 미세한 오차를 허용하는 비교법이나 적절한 반올림 함수를 사용하는 것이 중요합니다.
1// Floating point precision example and safe equality
2console.log("0.1 + 0.2 === 0.3 :", 0.1 + 0.2 === 0.3); // false
3
4function nearlyEqual(a, b, eps = 1e-12) {
5 return Math.abs(a - b) <= eps;
6}
7console.log("nearlyEqual(0.1+0.2, 0.3):", nearlyEqual(0.1 + 0.2, 0.3));
8// -> true
- 정확한 수치 비교에는 절대 오차(
eps)나 상대 오차를 사용하세요.
성능 팁
Math의 함수는 네이티브로 최적화되어 있어, 직접 구현한 동등한 로직보다 빠른 경우가 많습니다. 같은 계산(Math.PI / 180 등)이 반복문 내에서 반복된다면, 미리 변수에 저장해 오버헤드를 줄일 수 있습니다.
아래는 루프 외부에서 상수를 설정해 각도를 라디안으로 변환하는 예시입니다.
1// Cache conversion factor for performance
2const DEG_TO_RAD = Math.PI / 180;
3const RAD_TO_DEG = 180 / Math.PI;
4
5for (let deg = 0; deg < 360; deg += 10) {
6 // Use cached constant instead of computing each time
7 const rad = deg * DEG_TO_RAD;
8 // ... do work with rad
9}- 최적화 전에는 실제 병목을 프로파일러로 확인하는 것이 좋습니다.
- 자주 쓰이는 상수는 캐싱하는 것이 효율적입니다.
호환성 및 폴리필
Math 자체는 오래전부터 존재하지만, Math.cbrt, Math.log10, Math.log2, Math.hypot와 같은 일부 함수는 구형 환경에서 지원되지 않을 수 있습니다. 필요하다면 간단한 폴리필을 준비하세요.
Math.log2에 대한 간단한 폴리필 예시는 아래와 같습니다.
1// Polyfill for Math.log2 if needed
2if (!Math.log2) {
3 Math.log2 = function(x) {
4 return Math.log(x) / Math.LN2;
5 };
6}
7console.log("Math.log2(8):", Math.log2(8));많은 환경이 이미 지원하지만, 필요하다면 호환성을 확인하세요.
프로젝트의 타깃 환경에 따라 브라우저 지원 상황을 확인하세요.
실용 예제: 간단한 물리 시뮬레이션의 시간 기반 업데이트
마지막으로, 여러 Math 함수들을 조합한 실용 예제가 있습니다. 이 예제는 위치, 속도, 각도 제어를 갱신하는 매우 간단한 예시입니다.
물리 엔진의 극도로 단순화된 모델입니다.
1// Clamp value between min and max
2function clamp(v, min, max) {
3 return Math.max(min, Math.min(max, v));
4}
5
6// Normalize angle to [-PI, PI)
7function normalizeAngle(rad) {
8 return Math.atan2(Math.sin(rad), Math.cos(rad));
9}
10
11// Simple physics step example using Math utilities
12function step(state, dt) {
13 // state: { x, y, vx, vy, angle, angularVelocity }
14 // dt: time delta in seconds
15 // Integrate linear motion
16 state.x += state.vx * dt;
17 state.y += state.vy * dt;
18
19 // Integrate angular motion and normalize angle
20 state.angle = normalizeAngle(state.angle + state.angularVelocity * dt);
21
22 // Keep position within bounds [0, width] x [0, height]
23 state.x = clamp(state.x, 0, state.width);
24 state.y = clamp(state.y, 0, state.height);
25 return state;
26}
27
28const state = { x: 10, y: 10, vx: 2, vy: 0.5, angle: 0, angularVelocity: 0.1, width: 100, height: 100 };
29console.log("before:", state);
30step(state, 0.016); // simulate ~1 frame at 60fps
31console.log("after:", state);- 이처럼
Math의 도우미들을 조합하면 시뮬레이션 및 애니메이션 로직을 간략하게 만들 수 있습니다.
요약
Math는 상수와 기본 함수부터 고급 함수까지 아우르며 수치 처리의 토대를 제공합니다.- 난수, 삼각함수, 지수/로그, 반올림 등 목적에 맞춰 함수를 선택하고, 실용적인 사용을 위해
clamp나lerp같은 소규모 유틸리티도 직접 만들어 사용하세요. - 부동소수점 정밀도와 타깃 환경의 지원 상황에 유의하고, 필요에 따라 오차 허용 방식이나 폴리필도 준비하세요.
위의 기사를 보면서 Visual Studio Code를 사용해 우리 유튜브 채널에서 함께 따라할 수 있습니다. 유튜브 채널도 확인해 주세요.