Contenuto principale

Numeri in virgola mobile

Il termine "in virgola mobile" si riferisce a un insieme di tipi di dato che codificano numeri reali, comprese le frazioni e i decimali. I tipi di dato in virgola mobile consentono di avere un numero variabile di cifre dopo il punto decimale, mentre i tipi di dato in virgola fissa hanno un numero specifico di cifre riservate prima e dopo il punto decimale. Pertanto, i tipi di dato in virgola mobile possono rappresentare un intervallo di numeri più ampio rispetto ai tipi di dato in virgola fissa.

A causa della memoria limitata per la rappresentazione e l'archiviazione dei numeri, i computer possono rappresentare un insieme finito di numeri in virgola mobile con precisione finita. Questa precisione finita può limitare l'accuratezza dei calcoli in virgola mobile che richiedono valori esatti o un'elevata precisione, poiché alcuni numeri non sono rappresentati in modo esatto. Nonostante i loro limiti, i numeri in virgola mobile sono ampiamente utilizzati grazie alla rapidità di calcolo e alla precisione e all'intervallo sufficienti per risolvere problemi reali.

Numeri in virgola mobile in MATLAB

MATLAB® dispone di tipi di dato per numeri in virgola mobile a doppia precisione (double) e a singola precisione (single) conformi allo standard IEEE® 754. Per impostazione predefinita, MATLAB rappresenta i numeri in virgola mobile a doppia precisione. La doppia precisione consente di rappresentare i numeri con maggiore precisione, ma richiede più memoria rispetto alla singola precisione. Per preservare la memoria, è possibile convertire un numero in singola precisione utilizzando la funzione single.

È possibile memorizzare numeri compresi approssimativamente tra –3,4 × 1038 e 3,4 × 1038 utilizzando la doppia o la singola precisione. Se i numeri non rientrano in tale intervallo, memorizzarli utilizzando la doppia precisione.

Creazione di dati a doppia precisione

Poiché il tipo numerico predefinito per MATLAB è il tipo double, è possibile creare un numero in virgola mobile a doppia precisione con una semplice dichiarazione di assegnazione.

x = 10;
c = class(x)
c =
   'double'

È possibile convertire dati numerici, caratteri o stringhe, così come dati logici in doppia precisione utilizzando la funzione double. Ad esempio, convertire un numero intero con segno in un numero in virgola mobile a doppia precisione.

x = int8(-113);
y = double(x)
y =
   -113

Creazione di dati a singola precisione

Per creare un numero a singola precisione, utilizzare la funzione single.

x = single(25.783);

È possibile convertire dati numerici, caratteri o stringhe, così come dati logici in singola precisione utilizzando la funzione single. Ad esempio, convertire un numero intero con segno in un numero in virgola mobile a singola precisione.

x = int8(-113);
y = single(x)
y =
   single
   -113

Modalità di memorizzazione dei numeri in virgola mobile in MATLAB

MATLAB costruisce i tipi di dato in virgola mobile double e single secondo il formato IEEE e, per impostazione predefinita, utilizza l'arrotondamento al valore più vicino, con arrotondamento al numero pari in caso di equidistanza.

Un numero in virgola mobile x ha la forma:

x=1s(1+f)2e

dove:

  • s determina il segno.

  • f è la frazione o mantissa, che soddisfa 0 ≤ f < 1.

  • e è l'esponente.

s, f ed e sono determinati ciascuno da un numero finito di bit in memoria, con f ed e che dipendono dalla precisione del tipo di dato.

Come mostrato in questa tabella, la memorizzazione di un numero double richiede 64 bit.

BitLarghezzaUtilizzo
631Memorizza il segno, dove 0 è positivo e 1 è negativo
Da 62 a 5211Memorizza l'esponente, con bias pari a 1023
Da 51 a 052Memorizza la mantissa

Come mostrato in questa tabella, la memorizzazione di un numero single richiede 32 bit.

BitLarghezzaUtilizzo
311Memorizza il segno, dove 0 è positivo e 1 è negativo
Da 30 a 238Memorizza l'esponente, con bias pari a 127
Da 22 a 023Memorizza la mantissa

Valori massimi e minimi dei tipi di dato in virgola mobile

I tipi di dato a doppia e singola precisione hanno un valore massimo e minimo che è possibile rappresentare. Ai numeri al di fuori dell'intervallo rappresentabile viene assegnato il valore infinito positivo o negativo. Tuttavia, alcuni numeri compresi nell'intervallo rappresentabile non possono essere memorizzati esattamente a causa dei divari presenti tra numeri in virgola mobile consecutivi; i numeri non memorizzabili esattamente tendono a presentare errori di arrotondamento.

Valori massimi e minimi a doppia precisione

Trovare i valori positivi massimi e minimi che possono essere rappresentati con il tipo di dato double utilizzando rispettivamente le funzioni realmax e realmin.

m = realmax
m =
   1.7977e+308
n = realmin
n =
   2.2251e-308

realmax e realmin restituiscono i valori IEEE normalizzati. È possibile trovare i valori negativi massimi e minimi moltiplicando realmax e realmin per -1. Ai numeri maggiori di realmax o minori di –realmax vengono assegnati rispettivamente i valori di infinito positivo o negativo.

Valori massimi e minimi a singola precisione

Trovare i valori positivi massimi e minimi che possono essere rappresentati con il tipo di dato single chiamando le funzioni realmax e realmin con l'argomento "single".

m = realmax("single")
m =
   single
   3.4028e+38
n = realmin("single")
n =
   single
   1.1755e-38

È possibile trovare i valori negativi massimi e minimi moltiplicando realmax("single") e realmin("single") per –1. Ai numeri maggiori di realmax("single") o minori di –realmax("single") vengono assegnati rispettivamente i valori di infinito positivo o negativo.

Numeri interi massimi consecutivi in virgola mobile

Non tutti i numeri interi sono rappresentabili utilizzando tipi di dato in virgola mobile. Il numero intero massimo consecutivo, x, è il numero intero più grande rispetto al quale tutti i numeri interi inferiori o uguali a x possono essere rappresentati esattamente, ma x + 1 non può essere rappresentato nel formato in virgola mobile. La funzione flintmax restituisce il numero intero massimo consecutivo. Ad esempio, trovare il numero intero massimo consecutivo nel formato in virgola mobile a doppia precisione, ossia 253, utilizzando la funzione flintmax.

x = flintmax
x =
   9.0072e+15

Trovare il numero intero massimo consecutivo nel formato in virgola mobile a singola precisione, ossia 224.

y = flintmax("single")
y =
   single 
   16777216

Quando si converte un tipo di dato a numero intero in un tipo di dato in virgola mobile, i numeri interi che non sono rappresentabili esattamente nel formato in virgola mobile perdono precisione. flintmax, che è un numero in virgola mobile, è inferiore al numero intero più grande rappresentabile dai tipi di dato a numero intero che utilizzano lo stesso numero di bit. Ad esempio, flintmax per la doppia precisione è 253, mentre il valore massimo per il tipo int64 è 264 – 1. Pertanto, la conversione in doppia precisione di un numero intero maggiore di 253 comporta una perdita di precisione.

Precisione dei dati in virgola mobile

La precisione dei dati in virgola mobile può essere influenzata da diversi fattori:

  • Limiti dell'hardware del computer: ad esempio, un hardware con memoria insufficiente tronca i risultati dei calcoli in virgola mobile.

  • Divari presenti tra ciascun numero in virgola mobile e il numero in virgola mobile immediatamente superiore: questi divari sono presenti su qualsiasi computer e limitano la precisione.

Divari presenti tra numeri in virgola mobile

È possibile determinare la dimensione di una lacuna presente tra numeri in virgola mobile consecutivi utilizzando la funzione eps. Ad esempio, trovare la distanza tra 5 e il numero a doppia precisione immediatamente superiore.

e = eps(5)
e =
   8.8818e-16

Non è possibile rappresentare i numeri compresi tra 5 e 5 + eps(5) nel formato a doppia precisione. Se un calcolo a doppia precisione restituisce come risposta 5, il risultato è accurato entro eps(5). Questo raggio di precisione è spesso chiamato epsilon di macchina.

I divari presenti tra i numeri in virgola mobile non sono uguali. Ad esempio, la lacuna presente tra 1e10 e il numero a doppia precisione immediatamente superiore è maggiore della lacuna presente tra 5 e il numero a doppia precisione immediatamente superiore.

e = eps(1e10)
e =
   1.9073e-06

In modo analogo, trovare la distanza tra 5 e il numero a singola precisione immediatamente superiore.

x = single(5);
e = eps(x)
e = 
   single 
   4.7684e-07

I divari presenti tra i numeri a singola precisione sono maggiori rispetto a quelle presenti tra i numeri a doppia precisione, poiché esistono meno numeri a singola precisione. Quindi, i risultati dei calcoli a singola precisione sono meno precisi rispetto ai risultati dei calcoli a doppia precisione.

Durante la conversione di un numero a doppia precisione in un numero a singola precisione, è possibile determinare il limite superiore dell'arrotondamento del numero utilizzando la funzione eps. Ad esempio, quando si converte il numero a doppia precisione 3.14 in singola precisione, il numero viene arrotondato al massimo di eps(single(3.14)).

Divari presenti tra numeri interi consecutivi in virgola mobile

La funzione flintmax restituisce il numero intero massimo consecutivo nel formato in virgola mobile. Al di sopra di questo valore, i numeri interi consecutivi in virgola mobile presentano una lacuna maggiore di 1.

Trovare la lacuna presente tra flintmax e il numero in virgola mobile successivo utilizzando eps:

format long
x = flintmax
x =
   9.007199254740992e+15
e = eps(x)
e =
   2

Poiché eps(x) è pari a 2, il numero in virgola mobile immediatamente superiore che può essere rappresentato esattamente è x + 2.

y = x + e
y =
   9.007199254740994e+15

Se si aggiunge 1 a x, il risultato viene arrotondato a x.

z = x + 1
z =
   9.007199254740992e+15

Operazioni aritmetiche su numeri in virgola mobile

È possibile utilizzare un intervallo di tipi di dato nelle operazioni aritmetiche con numeri in virgola mobile con il tipo di dato del risultato determinato dai tipi di input. Tuttavia, quando si eseguono operazioni con tipi di dato diversi, alcuni calcoli potrebbero non essere esatti a causa di approssimazioni o conversioni intermedie.

Operandi a doppia precisione

È possibile eseguire operazioni aritmetiche di base con double e uno qualsiasi dei seguenti tipi di dato. Se uno o più operandi sono numeri interi scalari o array, l'operando double deve essere uno scalare. Il risultato è di tipo double, se non diversamente indicato.

  • single: il risultato è di tipo single.

  • double

  • int8, int16, int32, int64: il risultato ha lo stesso tipo di dato dell'operando a numero intero.

  • uint8, uint16, uint32, uint64: il risultato ha lo stesso tipo di dato dell'operando a numero intero.

  • char

  • logical

Operandi a singola precisione

È possibile eseguire operazioni aritmetiche di base con single e uno qualsiasi dei seguenti tipi di dato. Il risultato è di tipo single.

  • single

  • double

  • char

  • logical

Risultati inaspettati con l'aritmetica in virgola mobile

Quasi tutte le operazioni in MATLAB vengono eseguite in aritmetica a doppia precisione conforme allo standard IEEE 754. Poiché i computer rappresentano i numeri con una precisione finita, alcuni calcoli possono produrre risultati matematicamente non intuitivi. Alcuni problemi comuni che possono verificarsi durante il calcolo con numeri in virgola mobile sono l'errore di arrotondamento, la cancellazione, lo swamping e le conversioni intermedie. I risultati inaspettati non rappresentano bug in MATLAB e si verificano in qualsiasi software che utilizza numeri in virgola mobile. Per rappresentazioni razionali esatte dei numeri, valutare di utilizzare Symbolic Math Toolbox™.

Errore di arrotondamento

L'errore di arrotondamento può verificarsi a causa della rappresentazione a precisione finita dei numeri in virgola mobile. Ad esempio, il numero 4/3 non può essere rappresentato esattamente come frazione binaria. Di conseguenza, questo calcolo restituisce la quantità eps(1) anziché 0.

e = 1 - 3*(4/3 - 1)
e =
   2.2204e-16

In modo analogo, poiché pi non è una rappresentazione esatta di π, sin(pi) non è esattamente zero.

x = sin(pi)
x =
   1.2246e-16

L'errore di arrotondamento è più evidente quando vengono eseguite molte operazioni su numeri in virgola mobile, consentendo agli errori di accumularsi e aggravarsi. Una best practice consiste nel minimizzare il numero di operazioni, ove possibile.

Cancellazione

La cancellazione può verificarsi quando si sottrae un numero da un altro numero di grandezza approssimativamente uguale, misurata da eps. Ad esempio, eps(2^53) è pari a 2, quindi i numeri 2^53 + 1 e 2^53 hanno la stessa rappresentazione in virgola mobile.

x = (2^53 + 1) - 2^53
x =
   0

Quando possibile, provare a riscrivere i calcoli in una forma equivalente che eviti le cancellazioni.

Swamping

Lo swamping può verificarsi quando si eseguono operazioni su numeri in virgola mobile che differiscono di molti ordini di grandezza. Ad esempio, questo calcolo mostra una perdita di precisione che rende l'addizione irrilevante.

x = 1 + 1e-16
x =  
   1

Conversioni intermedie

Quando si eseguono operazioni aritmetiche con tipi di dato diversi, i calcoli intermedi e le conversioni possono produrre risultati imprevisti. Ad esempio, sebbene x e y siano entrambi pari a 0.2, sottraendoli si ottiene un risultato diverso da zero. Il motivo è che y viene convertito in double prima che venga eseguita la sottrazione. Il risultato della sottrazione viene quindi convertito in single, z.

format long 
x = 0.2
x = 
   0.200000000000000
y = single(0.2)
y = 
   single
   0.2000000
z = x - y
z = 
   single 
   -2.9802323e-09

Algebra lineare

I problemi comuni nell'aritmetica in virgola mobile, come quelli descritti sopra, possono aggravarsi quando vengono applicati a problemi di algebra lineare, poiché i calcoli correlati consistono tipicamente in più passaggi. Ad esempio, quando si risolve il sistema di equazioni lineari Ax = b, MATLAB avverte che i risultati potrebbero essere imprecisi perché la matrice dell'operando A è mal condizionata.

A = diag([2 eps]);
b = [2; eps];
x = A\b;
Warning: Matrix is close to singular or badly scaled. 
         Results may be inaccurate. RCOND = 1.110223e-16.

Riferimenti

[1] Moler, Cleve. Numerical Computing with MATLAB. Natick, MA: The MathWorks, Inc., 2004.

Vedi anche

Funzioni