`Math`-objekt

Denne artikel forklarer om Math-objektet.

Den forklarer trin for trin, fra grundlæggende brug til almindelige praktiske mønstre, samt faldgruber og modforanstaltninger.

YouTube Video

Math-objekt

JavaScripts Math-objekt tilbyder et sæt indbyggede værktøjer til numeriske beregninger.

Konstanter

Konstanter defineret i Math er nyttige, når man arbejder med værdier med høj præcision.

Følgende kode viser nogle typiske konstanter.

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
  • Disse konstanter kan bruges som de er til trigonometriske funktioner, logaritmiske konverteringer, normalisering og mere. For eksempel er Math.PI nødvendig for at konvertere vinkler til radianer.

Grundlæggende afrunding og absolutte værdier (abs, floor, ceil, round, trunc)

Afrunding og håndtering af fortegn bruges ofte, så det er vigtigt at forstå forskellene mellem Math.floor, Math.ceil og Math.round korrekt. Især når man arbejder med negative tal, kan resultaterne afvige fra intuitionen, så det er nødvendigt at være opmærksom på, hvordan hver afrundingsregel fungerer og bruge dem korrekt.

Følgende eksempler illustrerer forskellene mellem afrundingsfunktionerne.

 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 afrunder mod den mindre værdi for negative tal, så -3.7 bliver til -4.
  • Math.ceil afrunder mod den større værdi for negative tal, så -3.7 bliver til -3.
  • Math.round runder .5 op for positive tal, og for negative tal afrunder den mod nul.
  • Negative tal kan give resultater, der afviger fra intuitionen, så det er vigtigt at forstå, hvilken retning tallene afrundes i.
  • Afrundingsfunktioner bør vælges i henhold til brugssituationen. Brug for eksempel Math.floor til indeksberegninger, Math.ceil til øvre grænser og Math.trunc, når du blot vil fjerne decimaldelen.

Multiplikation, potens og rødder (pow, **, sqrt, cbrt, hypot)

Ophøjning i potens og kvadratrødder kan udføres med Math.pow eller med ** operatoren. Math.hypot beregner sikkert kvadratroden af summen af kvadrater (afstand).

Nedenfor er eksempler på potens og hypot. Math.hypot mindsker risikoen for over- eller underflow.

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 er nyttig, når man arbejder med trekantssider eller længden af flerdimensionelle vektorer.

Eksponential- og logaritmefunktioner (exp, log, log10, log2)

Eksponentialer og logaritmer bruges ofte i sandsynlighedsregning, eksponentiel henfald og skalering.

Næste er grundlæggende eksempler på exp og logaritmer. Brug den relevante funktion afhængigt af logaritmens base.

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
  • Naturlige logaritmer (Math.log) er standard i statistik og differentialligninger. Ti-tals-logaritmer og base-2-logaritmer vælges også afhængigt af anvendelsen.

Trigonometriske funktioner (sin, cos, tan, asin, acos, atan2)

Trigonometriske funktioner er essentielle for vinkelberegninger, rotationer og koordinattransformationer. Math.atan2(y, x) er nyttig til at beregne vinkler, idet den tager højde for kvadranterne korrekt.

Nedenfor er grundlæggende eksempler og brug af atan2. Vinkler skal behandles i radianer.

 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 kan sikkert bestemme vinklen af en vektor, hvilket gør den at foretrække til rotationer og retningsberegninger.

Tilfældig talgenerering (Math.random og praktiske mønstre)

Math.random() returnerer et jævnt fordelt tilfældigt tal i intervallet [0, 1). Du kan omdanne eller udvide det efter behov til heltalsintervaller eller normalfordelinger, for eksempel.

Følgende er eksempler på hjælpefunktioner til tilfældige tal. Hvis du har brug for kryptografisk sikre tilfældige tal, så brug 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 er praktisk til generel brug, men for spilgengivelser eller kryptografi er der brug for tiltag for reproducerbarhed eller sikkerhed.

Praktiske hjælpefunktioner (clamp, lerp, mapRange, vinkelnormalisering)

Det er nyttigt selv at skrive små hjælpefunktioner til ofte brugte matematiske opgaver.

Her er implementeringseksempler på ofte anvendte hjælpefunktioner.

 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));
  • Denne kode samler små hjælpefunktioner, der ofte bruges til numeriske operationer, såsom at begrænse værdier, interpolation, intervalomregning og vinkelnormalisering. clamp begrænser en værdi til et bestemt interval, mens lerp og mapRange udfører glat interpolation eller konvertering til et andet interval. Desuden normaliserer normalizeAngle altid vinkler til området [-π, π) for at stabilisere rotationsberegninger.
  • Disse hjælpefunktioner bruges ofte i grafik, spil og interaktionsprogrammering. normalizeAngle er vigtig for at sammenligne vinkelafstande og til interpolation.

Forholdsregler vedrørende flydende kommatal og afrunding (præcision og sammenligning)

JavaScript-tal er IEEE-754 dobbeltpræcision flydende tal (64-bit), så der skal udvises forsigtighed ved sammenligning eller afrunding af tal. For eksempel: 0.1 + 0.2 !== 0.3.

Her er et eksempel på håndtering af afrundingsfejl. Det er vigtigt at bruge sammenligninger, der tolererer små fejl, eller passende afrundingsfunktioner.

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
  • Til robuste numeriske lighedscheck bruges absolut fejl (eps) eller relativ fejl.

Ydelsestips

Math-funktionerne er optimeret af selve motoren og er ofte hurtigere end tilsvarende hjemmeskrevet logik. Hvis den samme beregning (fx Math.PI / 180) gentages i et loop, kan det reducere unødvendigt overhead at tildele den på forhånd til en variabel.

Nedenfor er et eksempel på at omregne grader til radianer ved at oprette en konstant uden for et loop.

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}
  • Det er bedst at verificere faktiske flaskehalse med en profiler, før du laver optimeringer.
  • Det er effektivt at cache konstanter, der bruges ofte.

Kompatibilitet og polyfills

Math har eksisteret længe, men nogle funktioner som Math.cbrt, Math.log10, Math.log2 og Math.hypot understøttes muligvis ikke i ældre miljøer. Forbered en simpel polyfill om nødvendigt.

Nedenfor er et eksempel på en simpel polyfill til 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));

Mange miljøer understøtter dem allerede, men tjek for kompatibilitet, hvis det er nødvendigt.

Tjek browsersupport i forhold til dit projekts målmiljø.

Praktisk eksempel: Tidstrin-opdateringer i en simpel fysiksimulering

Til sidst er her et praktisk eksempel, der kombinerer flere Math-funktioner. Dette er et meget simpelt eksempel på opdatering af position, hastighed og vinkelstyring.

Det er en stærkt forenklet model af en fysikmotor.

 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);
  • Ved at kombinere Math hjælpefunktioner som dette kan simulerings- og animationslogik gøres mere overskuelig.

Sammendrag

  • Math dækker alt fra konstanter og grundlæggende funktioner til avancerede, og udgør grundlaget for numerisk behandling.
  • Vælg funktioner alt efter deres formål, såsom tilfældige tal, trigonometriske funktioner, eksponentialer/logaritmer eller afrunding; og lav små hjælpefunktioner som clamp og lerp til praktisk brug.
  • Vær opmærksom på flydende kommatalpræcision og supportstatus for dit målmiljø, og forbered fejltolerance eller polyfills, hvis det er nødvendigt.

Du kan følge med i ovenstående artikel ved hjælp af Visual Studio Code på vores YouTube-kanal. Husk også at tjekke YouTube-kanalen.

YouTube Video