`Math`-object

Dit artikel legt het Math-object uit.

Het legt stap voor stap uit, van basisgebruik tot veelvoorkomende praktische patronen, evenals valkuilen en tegenmaatregelen.

YouTube Video

Math-object

Het Math-object van JavaScript biedt een reeks ingebouwde hulpmiddelen voor numerieke berekeningen.

Constanten

Constanten die in Math zijn gedefinieerd, zijn nuttig bij het werken met waarden met hoge precisie.

De volgende code toont enkele typische constanten.

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
  • Deze constanten kunnen direct worden gebruikt voor trigonometrische functies, logaritmische conversies, normalisatie en meer. Zo is Math.PI bijvoorbeeld nodig om hoeken naar radialen om te zetten.

Basisafronding en absolute waarden (abs, floor, ceil, round, trunc)

Afronden en het omgaan met tekens wordt vaak gebruikt, dus het is belangrijk om het verschil tussen Math.floor, Math.ceil en Math.round goed te begrijpen. Vooral bij het werken met negatieve getallen kunnen de resultaten afwijken van je intuïtie; wees dus voorzichtig met hoe elke afrondingsregel werkt, en gebruik ze op de juiste manier.

De volgende voorbeelden illustreren de verschillen tussen afrondingsfuncties.

 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 rondt naar beneden af voor negatieve getallen, dus -3.7 wordt -4.
  • Math.ceil rondt naar boven af voor negatieve getallen, dus -3.7 wordt -3.
  • Math.round rondt .5 naar boven af bij positieve getallen en naar nul bij negatieve getallen.
  • Negatieve getallen kunnen tot resultaten leiden die afwijken van je intuïtie; het is daarom belangrijk om duidelijk te begrijpen in welke richting getallen worden afgerond.
  • Afrondingsfuncties moeten gekozen worden op basis van het gebruiksdoel. Gebruik bijvoorbeeld Math.floor voor indexberekeningen, Math.ceil voor bovengrenzen en Math.trunc wanneer je alleen het decimale deel wilt laten vallen.

Vermenigvuldigen, machtsverheffen en worteltrekken (pow, **, sqrt, cbrt, hypot)

Machtsverheffen en vierkantswortels kunnen worden gedaan met Math.pow of met de **-operator. Math.hypot berekent veilig de vierkantswortel van de som van kwadraten (afstand).

Hieronder staan voorbeelden van machtsverheffen en hypot. Math.hypot vermindert het risico op overflow en 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 is handig bij berekeningen met driehoekszijden of multi-dimensionale vectorlengtes.

Exponentiële en logaritmische functies (exp, log, log10, log2)

Exponentiële functies en logaritmes worden vaak gebruikt in kansberekeningen, exponentieel verval en schalingsberekeningen.

Hierna volgen basisvoorbeelden van exp en logaritmes. Gebruik de juiste functie afhankelijk van het grondtal van de logaritme.

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
  • Natuurlijke logaritmes (Math.log) zijn standaard in de statistiek en differentiaalvergelijkingen. Gewone logaritmes en logaritmes met grondtal 2 worden ook gekozen afhankelijk van de toepassing.

Goniometrische functies (sin, cos, tan, asin, acos, atan2)

Goniometrische functies zijn essentieel voor hoekberekeningen, rotaties en coördinatentransformaties. Math.atan2(y, x) is handig om hoeken te berekenen waarbij correct rekening wordt gehouden met kwadranten.

Hieronder staan basisvoorbeelden en gebruik van atan2. Hoeken moeten in radialen worden behandeld.

 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 veilig de hoek van een vector bepalen en is daardoor te verkiezen bij rotaties en richtingberekeningen.

Willekeurige getalgeneratie (Math.random en praktische patronen)

Math.random() geeft een uniform verdeelde willekeurige waarde tussen [0, 1). Je kunt dit indien nodig omzetten of uitbreiden voor geheelgetal-bereiken of normale verdelingen.

Hieronder vind je voorbeelden van willekeurige getalhulpfuncties. Als je cryptografisch veilige willekeurige getallen nodig hebt, gebruik dan 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 is handig voor algemeen gebruik, maar voor gamereplays of cryptografie zijn maatregelen vereist voor herhaalbaarheid of veiligheid.

Praktische hulpmiddelen (clamp, lerp, mapRange, hoeken normaliseren)

Het is handig om kleine hulpfuncties te schrijven voor veelvoorkomende wiskundige taken.

Hieronder staan implementatievoorbeelden van veelgebruikte hulpfuncties.

 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));
  • Deze code bevat kleine hulpfuncties die veel worden gebruikt bij numerieke berekeningen, zoals het beperken van waarden, interpolatie, bereikomzetting en hoeken normaliseren. clamp beperkt een waarde tot een bepaald bereik, terwijl lerp en mapRange zorgen voor vloeiende interpolatie of omzetting naar een ander bereik. Bovendien normaliseert normalizeAngle altijd hoeken naar het bereik [-π, π) om rotatieberekeningen te stabiliseren.
  • Deze hulpmiddelen worden veel gebruikt in grafische toepassingen, games en interactieprogrammering. normalizeAngle is belangrijk voor het vergelijken van hoekverschillen en voor interpolatie.

Aandachtspunten bij drijvende-kommagetallen en afronding (precisie en vergelijking)

JavaScript-getallen zijn IEEE-754 double precision drijvende-kommagetallen (64-bits), dus wees voorzichtig bij het vergelijken of afronden van getallen. Bijvoorbeeld, 0.1 + 0.2 !== 0.3.

Hier is een voorbeeld om afrondingsfouten te behandelen. Het is belangrijk om vergelijkingen te gebruiken die kleine fouten tolereren, of geschikte afrondingsfuncties.

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
  • Voor robuuste numerieke gelijkheidscontroles gebruik je absolute fout (eps) of relatieve fout.

Prestatietips

De functies van Math zijn native geoptimaliseerd en vaak sneller dan zelfgeschreven vergelijkbare logica. Als dezelfde berekening (bijvoorbeeld Math.PI / 180) herhaaldelijk in een lus voorkomt, kun je deze vooraf aan een variabele toewijzen om onnodige overhead te verminderen.

Hieronder zie je een voorbeeld van het omzetten van graden naar radialen door buiten de lus een constante te definiëren.

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}
  • Het is het beste om daadwerkelijke knelpunten met een profiler te identificeren voordat je gaat optimaliseren.
  • Het is efficiënt om vaak gebruikte constanten in de cache op te slaan.

Compatibiliteit en polyfills

Math bestaat al lange tijd, maar sommige functies zoals Math.cbrt, Math.log10, Math.log2 en Math.hypot worden mogelijk niet ondersteund in oudere omgevingen. Voorzie indien nodig in een eenvoudige polyfill.

Hieronder vind je een voorbeeld van een eenvoudige polyfill voor 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));

Veel omgevingen ondersteunen ze al, maar controleer zo nodig de compatibiliteit.

Controleer de browserondersteuning afhankelijk van de doelomgeving van je project.

Praktisch voorbeeld: Tijdgestuurde updates in een eenvoudige fysicasimulatie

Tot slot volgt hier een praktisch voorbeeld waarin verschillende Math-functies worden gecombineerd. Dit is een heel eenvoudig voorbeeld voor het bijwerken van positie, snelheid en hoeksturing.

Het is een sterk vereenvoudigd model van een fysica-engine.

 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);
  • Door Math-hulpmiddelen op deze manier te combineren, kan de simulatie- en animatielogica compacter worden gemaakt.

Samenvatting

  • Math omvat alles van constanten en basisfuncties tot geavanceerde functies, en vormt de basis voor numerieke verwerking.
  • Kies functies op basis van hun doel, zoals willekeurige getallen, goniometrische functies, exponentiële/logaritmische functies of afrondingen; en maak kleine hulpmiddelen zoals clamp en lerp voor praktisch gebruik.
  • Let op drijvende-kommaprecisie en de ondersteuning in je doelomgeving, en voorzie in fouttolerantie of polyfills indien nodig.

Je kunt het bovenstaande artikel volgen met Visual Studio Code op ons YouTube-kanaal. Bekijk ook het YouTube-kanaal.

YouTube Video