`Math`-Objekt

Dieser Artikel erklärt das Math-Objekt.

Es erklärt Schritt für Schritt die grundlegende Verwendung bis hin zu häufigen praktischen Mustern, sowie Fallstricke und Gegenmaßnahmen.

YouTube Video

Math-Objekt

Das Math-Objekt von JavaScript bietet eine Sammlung eingebauter Werkzeuge für numerische Berechnungen.

Konstanten

Im Math-Objekt definierte Konstanten sind nützlich, wenn mit hochpräzisen Werten gearbeitet wird.

Der folgende Code zeigt einige typische Konstanten.

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
  • Diese Konstanten können direkt für trigonometrische Funktionen, logarithmische Umrechnungen, Normalisierung und mehr verwendet werden. Zum Beispiel wird Math.PI benötigt, um Winkel in Bogenmaß umzuwandeln.

Grundlegende Rundungsfunktionen und Absolutwerte (abs, floor, ceil, round, trunc)

Runden und die Behandlung von Vorzeichen werden häufig verwendet, daher ist es wichtig, die Unterschiede zwischen Math.floor, Math.ceil und Math.round genau zu verstehen. Gerade bei negativen Zahlen können die Ergebnisse von der Intuition abweichen. Daher ist es notwendig, genau zu wissen, wie jede Rundungsregel funktioniert und sie entsprechend einzusetzen.

Die folgenden Beispiele verdeutlichen die Unterschiede zwischen den Rundungsfunktionen.

 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 rundet bei negativen Zahlen in Richtung des kleineren Werts, daher wird aus -3.7 -4.
  • Math.ceil rundet bei negativen Zahlen in Richtung des größeren Werts, daher wird aus -3.7 -3.
  • Math.round rundet Kommazahlen ab .5 bei positiven Zahlen auf, und bei negativen Zahlen erfolgt das Runden zur Null hin.
  • Bei negativen Zahlen können Ergebnisse auftreten, die nicht der Intuition entsprechen. Es ist daher wichtig, genau zu wissen, in welche Richtung gerundet wird.
  • Rundungsfunktionen sollten je nach Anwendungsfall ausgewählt werden. Zum Beispiel sollte Math.floor für Indexberechnungen, Math.ceil für obere Grenzen und Math.trunc, wenn nur der Dezimalteil entfernt werden soll, verwendet werden.

Multiplikation, Potenzieren und Wurzeln (pow, **, sqrt, cbrt, hypot)

Potenzieren und Quadratwurzeln können mit Math.pow oder dem Operator ** durchgeführt werden. Math.hypot berechnet sicher die Quadratwurzel aus der Summe der Quadrate (Distanz).

Nachstehend Beispiele für Potenzieren und die Funktion hypot. Math.hypot minimiert die Auswirkungen von Überlauf und Unterlauf.

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 ist nützlich, wenn mit Dreiecksseiten oder mehrdimensionalen Vektorlängen gearbeitet wird.

Exponential- und Logarithmusfunktionen (exp, log, log10, log2)

Exponential- und Logarithmusfunktionen werden häufig in der Wahrscheinlichkeitsrechnung, dem exponentiellen Zerfall und beim Skalieren verwendet.

Im Folgenden Beispiele zu exp und Logarithmen. Die passende Funktion sollte je nach Logarithmus-Basis verwendet werden.

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
  • Natürliche Logarithmen (Math.log) sind Standard in Statistik und Differentialgleichungen. Zehner-Logarithmen und Zweier-Logarithmen werden je nach Anwendung ebenfalls ausgewählt.

Trigonometrische Funktionen (sin, cos, tan, asin, acos, atan2)

Trigonometrische Funktionen sind unerlässlich für Winkelberechnungen, Rotationen und Koordinatentransformationen. Math.atan2(y, x) ist nützlich, um Winkel unter Berücksichtigung der Quadranten korrekt zu berechnen.

Nachfolgend finden sich Beispiele und Verwendung von atan2. Winkel müssen im Bogenmaß verarbeitet werden.

 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 kann den Winkel eines Vektors sicher bestimmen und ist daher für Rotationen und Steuerberechnungen zu bevorzugen.

Zufallszahlengenerierung (Math.random und praktische Muster)

Math.random() gibt eine gleichmäßig verteilte Zufallszahl im Bereich [0, 1) zurück. Sie können ihn bei Bedarf zum Beispiel für Ganzzahlbereiche oder Normalverteilungen anpassen oder erweitern.

Im Folgenden finden Sie Beispiele für Zufallszahl-Hilfsfunktionen. Wenn kryptografisch sichere Zufallszahlen benötigt werden, sollte crypto.getRandomValues verwendet werden.

 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 ist für den allgemeinen Gebrauch praktisch, aber für Spiel-Wiederholungen oder Kryptographie sind Maßnahmen für Reproduzierbarkeit oder Sicherheit erforderlich.

Praktische Hilfsfunktionen (clamp, lerp, mapRange, Winkelnormalisierung)

Es ist hilfreich, kleine Hilfsfunktionen selbst zu schreiben, um häufig benötigte mathematische Aufgaben zu erledigen.

Hier sind Implementierungsbeispiele für häufig verwendete Hilfsfunktionen.

 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));
  • Dieser Code fasst kleine Hilfsfunktionen zusammen, die häufig für numerische Operationen wie Wertbegrenzung, Interpolation, Bereichsanpassung sowie Winkelnormalisierung verwendet werden. clamp begrenzt einen Wert auf einen bestimmten Bereich, während lerp und mapRange für eine sanfte Interpolation bzw. Konvertierung in einen anderen Bereich sorgen. Außerdem normalisiert normalizeAngle Winkel immer in den Bereich [-π, π), um Rotationsberechnungen zu stabilisieren.
  • Diese Hilfsfunktionen werden häufig in Grafik-, Spiele- und Interaktionsprogrammierung verwendet. normalizeAngle ist wichtig zum Vergleich von Winkelunterschieden sowie für Interpolationen.

Hinweise zu Gleitkommazahlen und Rundung (Präzision und Vergleich)

JavaScript-Zahlen sind IEEE-754-Doppelpräzisions-Gleitkommazahlen (64 Bit), daher ist Vorsicht bei Vergleichen oder Rundungen geboten. Zum Beispiel: 0.1 + 0.2 !== 0.3.

Hier ein Beispiel zum Umgang mit Rundungsfehlern. Es ist wichtig, Vergleiche zu verwenden, die kleine Fehler tolerieren, oder geeignete Rundungsfunktionen zu benutzen.

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
  • Für robuste numerische Gleichheitsprüfungen sollte der absolute Fehler (eps) oder der relative Fehler verwendet werden.

Leistungstipps

Die Funktionen des Math-Objekts sind nativ optimiert und oft schneller als handgeschriebene, äquivalente Logik. Wenn dieselbe Berechnung (z.B. Math.PI / 180) in einer Schleife wiederholt wird, kann deren vorherige Zuweisung zu einer Variablen unnötigen Overhead verringern.

Im Folgenden ein Beispiel zur Umwandlung von Grad in Bogenmaß, indem außerhalb einer Schleife eine Konstante erstellt wird.

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}
  • Am besten überprüft man mit einem Profiler potenzielle Engstellen, bevor Optimierungen vorgenommen werden.
  • Es ist effizient, häufig verwendete Konstanten zwischenzuspeichern.

Kompatibilität und Polyfills

Math selbst gibt es schon lange, aber einige Funktionen wie Math.cbrt, Math.log10, Math.log2 und Math.hypot werden möglicherweise in älteren Umgebungen nicht unterstützt. Bereiten Sie bei Bedarf ein einfaches Polyfill vor.

Nachfolgend ein Beispiel für ein einfaches Polyfill für 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));

Viele Umgebungen unterstützen sie bereits, aber prüfen Sie die Kompatibilität, falls notwendig.

Überprüfen Sie die Browserunterstützung entsprechend der Zielumgebung Ihres Projekts.

Praktisches Beispiel: Zeitabgestufte Aktualisierungen in einer einfachen Physiksimulation

Abschließend ein praktisches Beispiel, das mehrere Math-Funktionen kombiniert. Dies ist ein sehr einfaches Beispiel zur Aktualisierung von Position, Geschwindigkeit und Winkelkontrolle.

Es ist ein stark vereinfachtes Modell einer Physik-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);
  • Durch die Kombination solcher Math-Hilfsfunktionen kann Simulations- und Animationslogik kompakter umgesetzt werden.

Zusammenfassung

  • Math deckt alles von Konstanten und Basisfunktionen bis hin zu fortgeschrittenen Funktionen ab und bildet so die Grundlage für numerische Berechnungen.
  • Wählen Sie Funktionen je nach Einsatzzweck – zum Beispiel Zufallszahlen, trigonometrische Funktionen, Exponential-/Logarithmusfunktionen oder Rundungen – und erstellen Sie kleine Hilfsfunktionen wie clamp und lerp für den praktischen Einsatz.
  • Achten Sie auf Gleitkomma-Präzision und die Unterstützung Ihrer Zielumgebung und bereiten Sie gegebenenfalls Fehlertoleranzen oder Polyfills vor.

Sie können den obigen Artikel mit Visual Studio Code auf unserem YouTube-Kanal verfolgen. Bitte schauen Sie sich auch den YouTube-Kanal an.

YouTube Video