`Oggetto` Math ``
Questo articolo spiega l'oggetto Math.
Spiega passo dopo passo, dall'uso di base ai pattern pratici più comuni, oltre a insidie e relative contromisure.
YouTube Video
Oggetto Math ``
L'oggetto Math di JavaScript offre un insieme di funzioni integrate per i calcoli numerici.
Costanti
Le costanti definite in Math sono utili quando si lavora con valori ad alta precisione.
Il codice seguente mostra alcune costanti tipiche.
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
- Queste costanti possono essere usate così come sono per funzioni trigonometriche, conversioni logaritmiche, normalizzazione e altro. Ad esempio,
Math.PIè necessario per convertire gli angoli in radianti.
Arrotondamenti di base e valori assoluti (abs, floor, ceil, round, trunc)
Arrotondamenti e la gestione dei segni sono usati frequentemente, quindi è importante comprendere bene le differenze tra Math.floor, Math.ceil e Math.round. Soprattutto con i numeri negativi, i risultati possono differire dall'intuizione, quindi bisogna prestare attenzione a come funziona ciascuna regola di arrotondamento e usarle in modo appropriato.
I seguenti esempi illustrano le differenze tra le varie funzioni di arrotondamento.
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.floorarrotonda verso il valore più piccolo per i numeri negativi, quindi-3.7diventa-4.Math.ceilarrotonda verso il valore più grande per i numeri negativi, quindi-3.7diventa-3.Math.roundarrotonda .5 verso l'alto per i numeri positivi, mentre per i numeri negativi arrotonda verso lo zero.- I numeri negativi possono dare risultati diversi da quanto ci si aspetta, quindi è importante capire chiaramente in che direzione vengono arrotondati.
- Le funzioni di arrotondamento vanno scelte in base al caso d'uso. Ad esempio, usa
Math.floorper calcolare indici,Math.ceilper i limiti superiori eMath.truncquando vuoi semplicemente scartare la parte decimale.
Moltiplicazione, esponenziazione e radici (pow, **, sqrt, cbrt, hypot)
L'esponenziazione e le radici quadrate possono essere fatte con Math.pow o con l'operatore **. Math.hypot calcola in sicurezza la radice quadrata della somma dei quadrati (distanza).
Di seguito sono riportati esempi di esponenziazione e di hypot. Math.hypot riduce l'impatto di overflow e 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è utile quando si lavora con i lati di un triangolo o lunghezze di vettori multidimensionali.
Funzioni esponenziali e logaritmiche (exp, log, log10, log2)
Gli esponenziali e i logaritmi sono spesso usati in probabilità, decadimento esponenziale e scaling.
Di seguito alcuni esempi di base di exp e dei logaritmi. Assicurati di usare la funzione corretta, in base alla base del logaritmo.
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
- I logaritmi naturali (
Math.log) sono standard in statistica ed equazioni differenziali. Anche i logaritmi in base 10 e in base 2 vengono scelti in base all'applicazione.
Funzioni trigonometriche (sin, cos, tan, asin, acos, atan2)
Le funzioni trigonometriche sono essenziali per il calcolo degli angoli, le rotazioni e le trasformazioni di coordinate. Math.atan2(y, x) è utile per calcolare gli angoli tenendo conto correttamente dei quadranti.
Di seguito alcuni esempi di base e l'utilizzo di atan2. Gli angoli devono essere gestiti in radianti.
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
atan2permette di determinare in modo sicuro l'angolo di un vettore, il che lo rende preferibile per rotazioni e calcolo delle direzioni.
Generazione di numeri casuali (Math.random e pattern pratici)
Math.random() ritorna un numero casuale distribuito uniformemente nell'intervallo [0, 1). Puoi convertirlo o estenderlo secondo necessità per intervalli interi o distribuzioni normali, ad esempio.
I seguenti sono esempi di funzioni di utilità per numeri casuali. Se hai bisogno di numeri casuali sicuri dal punto di vista crittografico, usa 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è comodo per l'uso generale, ma per replay di giochi o crittografia sono necessarie contromisure per la riproducibilità o la sicurezza.
Helper pratici (clamp, lerp, mapRange, normalizzazione angoli)
È utile scrivere piccole funzioni di utilità per le operazioni matematiche più usate frequentemente.
Ecco alcuni esempi di implementazione di utility comunemente usate.
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));- Questo codice raccoglie piccole utility comunemente usate per operazioni numeriche, come il clamp dei valori, interpolazioni, mappature di range e normalizzazione degli angoli.
clamplimita un valore a un certo intervallo, mentrelerpemapRangerealizzano interpolazioni o conversioni fluide ad altri intervalli. Inoltre,normalizeAnglenormalizza sempre gli angoli nell'intervallo[-π, π)per stabilizzare i calcoli sulle rotazioni. - Questi helper sono usati di frequente in grafica, giochi e programmazione di interazione.
normalizeAngleè importante per confrontare differenze angolari e per l'interpolazione.
Avvertenze su floating point e arrotondamenti (precisione e confronto)
I numeri in JavaScript sono floating point a doppia precisione IEEE-754 (64 bit), quindi occorre fare attenzione nei confronti e negli arrotondamenti. Ad esempio, 0.1 + 0.2 !== 0.3.
Ecco un esempio di gestione degli errori di arrotondamento. È importante usare confronti che tollerano piccoli errori, o funzioni di arrotondamento appropriate.
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
- Per controlli affidabili di uguaglianza numerica, usa errori assoluti (
eps) o errori relativi.
Consigli sulle prestazioni
Le funzioni di Math sono ottimizzate nativamente e spesso più veloci rispetto a una logica scritta a mano equivalente. Se lo stesso calcolo (es. Math.PI / 180) viene ripetuto in un ciclo, assegnarlo preventivamente a una variabile riduce overhead inutili.
Di seguito un esempio di conversione da gradi a radianti creando una costante fuori dal ciclo.
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}- È meglio verificare i veri punti critici con un profiler prima di effettuare ottimizzazioni.
- È efficiente memorizzare in cache le costanti usate frequentemente.
Compatibilità e polyfill
Math esiste da molto tempo, ma alcune funzioni come Math.cbrt, Math.log10, Math.log2 e Math.hypot potrebbero non essere supportate in ambienti più vecchi. Prepara un semplice polyfill se necessario.
Di seguito un esempio di semplice polyfill per 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));Molti ambienti li supportano già, ma verifica la compatibilità se necessario.
Verifica il supporto dei browser in base all'ambiente target del tuo progetto.
Esempio pratico: aggiornamento a intervalli in una semplice simulazione fisica
Infine, ecco un esempio pratico che combina varie funzioni di Math. Questo è un esempio molto semplice di aggiornamento di posizione, velocità e controllo dell'angolo.
È un modello fortemente semplificato di un motore fisico.
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);- Combinando helper di
Mathin questo modo si può rendere più concisa la logica di simulazione e di animazione.
Riepilogo
Mathcopre tutto, dalle costanti alle funzioni di base e avanzate, fungendo da fondamento per l'elaborazione numerica.- Scegli le funzioni in base alla loro utilità: numeri casuali, funzioni trigonometriche, esponenziali/logaritmi o arrotondamenti; e crea piccole utility come
clampelerpper usi pratici. - Presta attenzione alla precisione dei floating point e al supporto del tuo ambiente di destinazione, e prepara tolleranza agli errori o polyfill se necessario.
Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.