4.1 Arrotondare i numeri in virgola mobile
I numeri in virgola mobile in inglese sono chiamati floating point number — numeri con virgola mobile: negli USA per separare la parte intera da quella decimale si usa il punto. Da qui deriva il nome float.
Come abbiamo già visto, quando si converte un numero in virgola mobile (float) in un intero (int), viene sempre arrotondato verso il basso al numero intero — la sua parte decimale viene semplicemente scartata. Ma è facile immaginare una situazione in cui un numero in virgola mobile deve essere arrotondato al numero intero più vicino. Cosa fare in tale situazione?
Per questo motivo in Python esiste la funzione integrata round(). È stata creata prima della libreria math, quindi non ne fa parte. Le funzioni per arrotondare verso il basso e verso l'alto si trovano nella libreria math.
La funzione round() arrotonda il numero al numero intero più vicino:
round(numero_in_virgola_mobile)
Questa funzione restituirà il numero intero più vicino al numero in virgola mobile passato a essa. È importante notare che se la parte decimale del numero è uguale a 0.5, la funzione round() usa il metodo di arrotondamento al numero intero pari più vicino. Questo si chiama "arrotondamento bancario" e permette di ridurre l'errore sistematico durante arrotondamenti multipli. Ad esempio:
Esempi:
| Comando | Risultato |
|---|---|
| x = round(4.1) | 4 |
| x = round(4.5) | 4 |
| x = round(4.9) | 5 |
| x = round(5.5) | 6 |
La funzione math.ceil() arrotonda il numero all'intero superiore, esempi:
| Comando | Risultato |
|---|---|
| x = math.ceil(4.1) | 5 |
| x = math.ceil(4.5) | 5 |
| x = math.ceil(4.9) | 5 |
La funzione math.floor() arrotonda il numero all'intero inferiore, esempi:
| Comando | Risultato |
|---|---|
| x = math.floor(4.1) | 4 |
| x = math.floor(4.5) | 4 |
| x = math.floor(4.9) | 4 |
Anche se per arrotondare un numero all'intero inferiore è più facile usare la funzione di conversione del tipo int():
| Comando | Risultato |
|---|---|
| x = int(4.9) | 4 |
Se trovi difficile ricordare questi comandi, può aiutare una piccola lezione di inglese:
math— matematicaround— arrotondareceiling— soffittofloor— pavimento
4.2 Struttura dei numeri in virgola mobile
Il tipo float in Python può contenere valori nel range da -1.7*10308 a +1.7*10308. Tale enorme range di valori è spiegato dal fatto che il tipo float è strutturato in modo completamente diverso rispetto ai tipi interi. Ogni variabile di tipo float contiene due numeri: il primo si chiama mantissa e il secondo esponente.
Supponiamo di avere il numero 123456789, e lo abbiamo salvato in una variabile di tipo float. Allora il numero verrà convertito nel formato 1.23456789*108, e all'interno del tipo float verranno memorizzati due numeri — 23456789 e 8. In rosso è evidenziata la "parte significativa del numero" (mantissa), in verde — l'esponente.
Questo approccio permette di memorizzare numeri molto grandi o molto piccoli. Ma poiché 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 il segno dell'esponente), la lunghezza massima della mantissa è limitata a 15 cifre.
Questa è una descrizione molto semplificata della struttura dei numeri in virgola mobile, puoi cercare su Google per una spiegazione più completa.
4.3 Perdita di precisione nel lavoro con i numeri in virgola mobile
Lavorando con i numeri in virgola mobile bisogna sempre tenere a mente che sono numeri imprecisi. Ci saranno sempre errori di arrotondamento, errori di conversione da sistema decimale a binario e, infine, il più comune — perdita di precisione durante l'addizione/sottrazione di numeri di dimensioni troppo diverse.
L'ultimo è la situazione più inaspettata per i principianti nella programmazione.
Se sottrai il numero 109 da 1/109, otterrai nuovamente 109.
| Sottrazione di numeri di dimensioni troppo diverse | Spiegazione |
|---|---|
|
Il secondo numero è troppo piccolo e la sua parte significativa viene ignorata (evidenziata in grigio). In arancione sono evidenziate 15 cifre significative. |
Cosa dire, la programmazione non è matematica.
4.4 Pericolo nel confrontare i numeri in virgola mobile
Un altro pericolo insidia i programmatori nel confronto dei numeri in virgola mobile. Poiché lavorando con questi numeri si possono accumulare errori di arrotondamento, ci sono situazioni in cui i numeri in virgola mobile dovrebbero essere uguali, ma non lo sono. E viceversa: i numeri dovrebbero non essere uguali, ma lo sono.
Esempio:
| Comando | Spiegazione |
|---|---|
| a = 1000000000.0 b = 0.000000001 c = a – b | La variabile a avrà il valore 1000000000.0 La variabile c avrà il valore 1000000000.0 (il numero nella variabile b è troppo piccolo) |
Nell'esempio sopra, a e c non dovrebbero essere uguali, ma lo sono.
Oppure prendiamo un altro esempio:
| Comando | Spiegazione |
|---|---|
| a = 1.00000000000000001 b = 1.00000000000000002 | La variabile a avrà il valore 1.0 La variabile b avrà il valore 1.0 |
Nella pratica i numeri in virgola mobile vengono confrontati così:
Si prende un numero molto piccolo. Se la differenza tra i numeri (in valore assoluto) è minore di questo numero piccolo, allora vengono considerati uguali. Esempio:
a = 0.00000000012
b = 0.000000000011
if abs(a - b) < 0.00001:
print("uguali")
else:
print("non uguali")
GO TO FULL VERSION