1.1 Arrotondamento dei numeri decimali
I numeri decimali in inglese si chiamano floating point number – numeri a virgola mobile: negli USA per separare la parte intera da quella decimale si usa il punto. Da qui il nome float.
Come abbiamo già discusso, quando si trasforma un numero decimale (float) in un intero (int), viene sempre arrotondato verso il basso — la parte decimale viene semplicemente scartata. Ma si può immaginare facilmente una situazione in cui il numero decimale deve essere arrotondato semplicemente al numero intero più vicino o addirittura verso l'alto. Che fare?
Per questo caso in JavaScript esiste una funzione integrata round()
. È stata inventata prima della creazione della libreria Math, quindi non ne fa parte. Le funzioni per l'arrotondamento verso il basso e verso l'alto si trovano nella libreria math.
Funzione Math.round()
La funzione Math.round()
arrotonda il numero al numero intero più vicino:
Math.round(numero_decimale)
Questa funzione restituirà il numero intero più vicino al numero decimale passato.
Esempi:
Comando | Risultato |
---|---|
let x = Math.round(4.1); |
4 |
let x = Math.round(4.5); |
5 |
let x = Math.round(4.9); |
5 |
Funzione Math.ceil()
La funzione Math.ceil()
arrotonda il numero verso l'alto:
Comando | Risultato |
---|---|
let x = Math.ceil(4.1); |
5 |
let x = Math.ceil(4.5); |
5 |
let x = Math.ceil(4.9); |
5 |
Funzione Math.floor()
La funzione Math.floor()
arrotonda il numero verso il basso:
Comando | Risultato |
---|---|
let x = Math.floor(4.1); |
4 |
let x = Math.floor(4.5); |
4 |
let x = Math.floor(4.9); |
4 |
Se ti è difficile ricordare questi comandi, un piccolo aiuto di inglese ti sarà utile:
- math — matematica
- round — cerchio/arrotondare
- ceiling — soffitto
- floor — pavimento
1.2 Il meccanismo dei numeri a virgola mobile
Il tipo number in JavaScript può memorizzare valori nell'intervallo da -1.7*10308 a +1.7*10308. Questo enorme intervallo di valori è spiegato dal fatto che il tipo number è strutturato in modo completamente diverso rispetto ai tipi interi. Ogni variabile di tipo number contiene due numeri: il primo è chiamato mantissa, e il secondo — esponente.
Supponiamo di avere un numero 123456789, e lo memorizziamo in una variabile di tipo number. Allora il numero verrà convertito in 1.23456789*108, e all'interno del tipo number verranno memorizzati i numeri — 1.23456789 e 8. In rosso è evidenziata la “parte significativa del numero” (mantissa), in blu l'esponente.
Questo approccio consente di memorizzare sia numeri molto grandi che molto piccoli. Ma dato che la dimensione del numero è limitata a 8 byte (64 bit) e parte dei bit viene utilizzata per memorizzare l'esponente (così come il segno del numero e quello dell'esponente), la lunghezza massima della mantissa è limitata a 15 cifre.
Questa è una descrizione molto semplificata del meccanismo dei numeri decimali: puoi trovare una descrizione più completa qui.
1.3 Perdita di precisione nei calcoli con numeri decimali
Quando si lavora con i numeri decimali è sempre necessario tener presente che i numeri decimali sono imprecisi. Ci saranno sempre errori di arrotondamento, errori di conversione dal sistema decimale al binario e, infine, il caso più comune — perdita di precisione nelle operazioni di somma/sottrazione di numeri con dimensioni molto diverse.
L'ultimo è il caso più sorprendente per i principianti della programmazione.
Se dal numero 109 si sottrae 1/109, otterremo di nuovo 109.
Sottrazione di numeri con dimensioni molto diverse | Spiegazione |
---|---|
1000000000.000000000 - 0.000000001 1000000000.000000000 |
Il secondo numero è troppo piccolo, e la sua parte significativa viene ignorata (evidenziata in grigio). In rosso sono evidenziate 15 cifre significative. |
Che dire, la programmazione non è matematica.
1.4 Il rischio di confrontare numeri decimali
Un altro rischio per i programmatori è nel confrontare i numeri decimali. Poiché lavorando con questi numeri possono accumularsi errori di arrotondamento, possono verificarsi situazioni in cui i numeri decimali dovrebbero essere uguali, ma non lo sono. E viceversa: i numeri dovrebbero essere diversi, ma sono identici.
Esempio:
Comando | Spiegazione |
---|---|
let a = 1000000000.0 let b = 0.000000001 let c = a – b
|
Nella variabile a ci sarà il valore 1000000000.0 .Nella variabile c ci sarà il valore 1000000000.0 (il numero nella variabile b è troppo piccolo).
|
Nell'esempio precedente a
e c
non dovrebbero essere uguali, ma lo sono.
Oppure prendiamo un altro esempio:
Comando | Spiegazione |
---|---|
let a = 1.00000000000000001 let b = 1.00000000000000002
|
Nella variabile a ci sarà il valore 1.0 .Nella variabile b ci sarà il valore 1.0 .
|
In pratica i numeri decimali vengono confrontati così:
Se la differenza tra i numeri (in valore assoluto) è inferiore a un certo numero molto piccolo, vengono considerati uguali.
Esempio:
let a = 0.00000000012;
let b = 0.000000000011;
if (Math.abs(a - b) < 0.00001) {
console.log("uguali");
} else {
console.log("non uguali");
}
GO TO FULL VERSION