Capitolo 7 - APPROSSIMAZIONE ED ERRORI

 

 

 

            7.1. - Errori di rappresentazione in macchina.

 

                Le operazioni aritmetiche (somma, differenza, prodotto e divisione) eseguite su una macchina da calcolo hanno proprietà diverse rispetto alle loro omologhe della Teoria dei Numeri, che non é interessata ai vincoli fisici del procedimento operativo, quanto alle definizione teorica degli algoritmi.

 

                Riepiloghiamo le caratteristiche principali della aritmetica finita basata sulla numerazione binaria con un numero finito di posizioni. La limitazione delle cifre binarie comporta conseguenze diverse, a seconda che il dato sia un numero intero, rappresentato nella naturale notazione posizionale, oppure non intero, rappresentato invece nella forma esponenziale normalizzata.

 

                Nel primo caso si ha una aritmetica esattamente equivalente a quella ordinaria nei limiti dello spazio di rappresentazione dei numeri (ad esempio tra -32738 e +32737), ma molto diversa se i risultati delle operazioni vanno al di fuori dei limiti stessi. Esiste comunque una regolarità, perché l'aritmetica ottenuta é in realtà quella modulo n, ove n è esattamente il numero di configurazioni possibili per i bit impiegati; se questi sono k, allora n = 2k.

 

                Nel secondo caso, invece, la rappresentazione di ogni valore non intero é limitata nell'ordine di grandezza dallo spazio disponibile per la caratteristica, che é un intero al di fuori dei cui limiti il calcolo perde ogni significato, e nella precisione dallo spazio per la mantissa, che comporta invece una quasi sistematica perdita di informazione nella rappresentazione della sequenza di cifre significative, solo alleviata dall'eseguire sempre operazioni di arrotondamento (anziché di troncamento) sulla prima cifra non più rappresentabile.

 

                Come si é visto, per le principali forme di rappresentazione dei numeri non interi la sequenza di cifre decimali esatte può essere al massimo di 7 o di 13, a seconda che il numero sia in semplice o in doppia precisione, mentre le potenze del 10 hanno come rispettivi campi di variazione  -38..38, oppure  -308..308.

 

                L'analisi della propagazione e le tecniche di controllo degli errori si riferiscono soprattutto al caso dei numeri non interi, che secondo l'abitudine consolidata dei linguaggi di programmazione si dicono reali.

 

                Il problema posto da questo tipo di errori non é però nuovo, né é nato con il calcolo automatico; è invece già presente nella normale esperienza di calcolo manuale, anche se quest'ultima permette di operare con maggiore elasticità rispetto alla macchina, poiché è possibile ampliare 'strada facendo' lo spazio per la scrittura dei numeri.

 

                Ma anche nella pratica manuale é necessario fare ricorso ad approssimazioni (arrotondamenti e troncamenti), poiché non è possibile operare - ad esempio incolonnare per una somma - se non su un numero finito di posizioni.

 

                L'analisi degli errori di calcolo é stata quindi approfondita e stabilizzata molto prima della comparsa dei calcolatori moderni, che non hanno per questo aspetto portato molti elementi sostanzialmente nuovi.

 

 

 

 

 

            7.2. - Errore assoluto e relativo.

 

Esempio 2.1. - Si considerino la rappresentazione di Pigreco con due cifre decimali per la parte frazionaria ed il suo valore 'vero'

 

  (7.2.1)                   p' = 3.14                               p = 3.1415.......

 

L'errore commesso con l'approssimazione può essere considerato dai due punti di vista, quello assoluto della differenza, oppure quello relativo, che ne misura il 'peso' percentuale:

 

  (7.2.2)                   ea = p' - p = -0.0015...

                               er = ( p' - p ) / p = -0.0015... / 3.1415... = -0.000477...

 

Esempio 2.2. - Considerando ora un altro numero nelle stesse condizioni:

 

  (7.2.3)                   q' = 0.01                               q = 0.0115.......

 

l'errore assoluto é lo stesso del caso precedente, mentre il relativo:

 

  (7.2.4)                   er = ( q' - q ) / q = -0.0015... / 0.015... = -0.1

 

passa da circa 5 su 10000 a circa 10 su 100. Come era intuibile, l'errore commesso, che é in assoluto uguale nei due casi, é però molto più 'grave' nel secondo.

 

 

                Indichiamo con x' il valore approssimato di un numero e con x il suo valore esatto; i due tipi di errori sono allora definiti dalle espressioni:

 

  (7.2.5)                   a(x') = x' - x ,

  (7.2.5')                  r(x') = ( x' - x ) / x  = a(x') / x

 

che si possono scrivere nelle forma:

 

  (7.2.6)                   x' = x + a(x') ,

  (7.2.6')                  x' = x * ( 1 + r(x') ) .

 

                L'errore assoluto a(x') misura fino a quale posizione le cifre della scrittura decimale sono esatte, mentre dall'errore relativo si può stabilire  quante cifre significative sono esatte. Mentre il valore della prima informazione dipende dall'ordine di grandezza del numero interessato, la seconda non necessita di alcun altro riferimento ed é naturalmente collegabile alla rappresentazione esponenziale normalizzata.

 

                Nei due esempi abbiamo supposto noto il valore 'vero' dei numeri (p e q rispettivamente) ed abbiamo artificialmente approssimato imponendo l'impiego di due sole cifre nella parte frazionaria.

 

                In generale si dispone però solo del valore approssimato (o stimato) x', mentre x é sconosciuto; per le regole dell'arrotondamento si può quindi solo asserire:

 

  (7.2.7)                   | a(x') |  =  | x' - x | 0.5 * 10k ,

 

ove k é l'esponente (generalmente negativo) che colloca il  '5'  nella prima posizione decimale successiva all'ultima cifra scritta nell'espressione di x.

 

                Ad esempio, considerando i soli valori p' della (7.2.1) e q' della (7.2.3), in entrambi i casi per l'errore assoluto si ha:

 

  (7.2.8)                   | a(p') |  =  | a(q') |  0.005

 

che é in fondo solo un altro modo di dire che le cifre scritte sono 'le più esatte possibile'.

 

                Gli errori effettivi degli esempi sono in realtà notevolmente inferiori rispetto all'estremo superiore (7.2.8); tale caratteristica rimane vera nell'analisi della propagazione degli errori nelle singole operazioni aritmetiche e nelle loro sequenze.

 

                Dall'essere normalmente x sconosciuto (come accade ad esempio nelle misure fisiche) discende una ulteriore conseguenza: la (7.2.5) è  inapplicabile e per la stima degli errori e della loro propagazione deve essere sostituite dalla più ampia condizione:

 

  (7.2.10) | a(x') |  =  0.5 * 10k ,

 

ove k è la potenza del 10 che coincide con la posizione ordinale della prima cifra decimale non rappresentata (troncata o arrotondata).

 

                Le (7.2.6) ci permettono di studiare il comportamento degli errori nelle operazioni aritmetiche; nel seguito indichiamo con   x'  ed  y' le  rispettive approssimazioni di due numeri  x  ed  y.

 

 

 

 

 

            3.- Somma e sottrazione

 

                Poiché non vi sono ipotesi sui segni dei due numeri, e le approssimazioni per arrotondamento possono essere indifferentemente per difetto o per eccesso (negative o positive), non vi é alcuna reale differenza tra la somma e la sottrazione.

 

                Consideriamo quindi solo la somma, iniziando dagli errori assoluti; per la (7.2.6)  y' = y + a(y) e:

 

  (7.3.1)                   x' + y' = ( x + y ) + ( a(x') + a(y') ) ,  ossia                     a(x'+y') = a(x') + a(y')  ;

 

il caso peggiore è quello in cui i due errori hanno il medesimo segno, poiché nell'altro gli errori si eliminano almeno parzialmente a vicenda, per cui:

 

  (7.3.2)                   L'errore assoluto della somma o della sottrazione di due numeri non supera

                               la somma dei valori assoluti dei due errori assoluti.

 

                Per quanto riguarda l'errore relativo, utilizziamo la seconda relazione in (7.2.6):

 

  (7.3.3)                   r ( x' + y'  ) = a ( x' + y' ) / ( x + y ) ( a(x') + a(y') ) / ( x + y )

                                                       = a(x') / ( x + y ) + a(y') / ( x + y )           

               

e nell'ipotesi che i due numeri abbiano il medesimo segno si ha:

 

  (7.3.4)                   r ( x' + y' ) r(x') + r(y') ,

 

relazione che é all'incirca verificata anche quando i due segni sono diversi, ma sono pure abbastanza diversi gli ordini di grandezza dei due dati.

 

                Ne segue che la sottrazione é l'operazione più 'rischiosa' dal punto di vista della precisione, come mostra l'esempio che segue.

 

Esempio 3.1.- L'errore relativo può facilmente diventare molto grande, cioè la perdita in cifre significative può essere molto consistente, quando i due numeri hanno segno opposto e sono molto vicini tra loro; siano infatti dati:

 

  (7.3.5)                   x = 0.1112131415... ,                        y = -0.1112031405... ,

 

la cui somma esatta sulle dieci cifre significative considerate é  x + y = 0.0000100010...., cioè possiede almeno cinque cifre significative a partire dalla prima non nulla.

 

Se x' ed y' sono valori approssimati di x ed y limitati ad otto cifre decimali, si ha:

 

  (7.3.6)                   x' = 0.11121314,                y = -0.11120314, x + y = 0.00001000....

 

e le cifre significative sono ridotte ad una soltanto.

 

 

 

 

 

 

            4.- Prodotto e divisione

 

 

                Per queste due operazioni il risultato più significativo si ottiene per i valori relativi; con le stesse notazioni utilizzate in precedenza, si ha infatti per il prodotto:

 

  (7.4.1)                   x' * y'    = x * ( 1 + r(x') ) * y * ( 1 + r(y') )

                                               = x * y + ( 1 + r(x') + r(y') + r(x') * r(y') )

 

l'ultimo termine in parentesi,  r(x') * r(y'), é il prodotto di due valori generalmente vicini a zero e si comporta sostanzialmente come un infinitesimo di ordine due, vale a dire che si ha:

 

  (7.4.2)                   r ( x' * y' ) @  r(x') + r(y' )

 

                Per la divisione, invece:

 

  (7.4.3)                   x' / y'     = ( x * ( 1 + r(x') ) / ( y * ( 1 + r(y') )

                                               = ( x / y ) * ( ( 1 + r(x') ) * ( 1 - r(y') ) / ( 1 - r2(y') ) ,

 

che, eliminando ancora la componente quadratica, conduce a:

 

  (7.4.4)                   r ( x' * y' ) @  r(x') - r(y')

 

                Poiché, al solito, non consideriamo i segni, il massimo errore relativo in un prodotto o una divisione è pari circa alla somma dei due errori relativi. Il risultato ottenuto é un po’ meno preciso di quello sulle somme e le sottrazioni e l'ambiguità del 'circa' preannunzia casi limite in cui l'errore può andare fuori controllo, come nel caso dell'esempio 3.1.

 

                In quanto agli errori assoluti, ci limitiamo alle espressioni finali, che possono facilmente essere derivate come esercizio:

 

  (7.4.5)                   a ( x' * y' ) @  ( x * a(y') + y * a(y') )

 

  (7.4.6)                   a ( x' / y' ) @  ( ( y * a(x') - x * a(y') ) / y )

                                                   = a(x') + ( x / y ) * a(y')

 

e, come si vede, la relazione con i due errori assoluti  a(x'), a(y') é ancora più complessa.

 

 

 

 

 

            5. - Propagazione degli errori

 

 

                Come già rilevato in precedenza, l'errore relativo é generalmente quello di maggior significato; per di più, come mostrano le  (7.3.1), (7.3.4), (7.4.1) e (7.4.4), esso si comporta in modo uniforme per le quattro operazioni, con la sola eccezione della differenza in un caso particolare, che può essere tenuto sotto controllo con opportune strategie di calcolo.

 

                Non é stato trattato a parte il caso della potenza, poiché esso si riduce ad un certo numero  di moltiplicazioni se l'esponente é intero (più una divisione finale se l'intero é negativo), ed ad una sequenza più complessa se esso non é intero; quest'ultimo caso deve quindi considerarsi assimilato a quello della valutazione di funzioni numeriche più generali.

 

                Lo studio della propagazione degli errori si riferisce appunto alla valutazione numerica delle espressioni formate da arbitrarie sequenze di operazioni aritmetiche semplici.

 

                Con le riserve già fatte per certe sottrazioni, la propagazione degli errori segue una semplice legge additiva:

 

  (7.5.1)                   se una espressione aritmetica comporta la esecuzione di  n operazioni, l'errore

                               relativo del valore dell'espressione non supera   n * e  , ove  e  é il massimo

                               valore assoluto degli errori relativi nei dati dell'espressione.

 

 

                Per quanto osservato con la (7.2.7) e (7.2.10),  e  ha di norma la forma  0.5 * 10k ; per sequenze di calcoli anche relativamente modeste, ci si dovrebbe aspettare una crescita abbastanza rapida (lineare) dell'errore, ma si può facilmente constatare che in genere l'errore effettivo é molto minore rispetto all'estremo superiore che figura nella (7.5.1).

 

                Il motivo é già emerso, almeno in parte: se si opera, come accade di norma, con arrotondamenti, i numeri di approssimazioni in eccesso ed in difetto tendono a bilanciarsi, e si raggiungono gli errori massimi solo quando le due approssimazioni sono avvenute nello stesso senso, entrambe sul rispettivo valore massimo.

 

  (7.5.2)                   La propagazione degli errori é quindi un fenomeno che deve essere analizzato

                               con strumenti statistici, determinandone la distribuzione attorno ad un valore

                               medio, da intendersi come errore probabile. Senza entrare nel merito di tale

                               analisi, ci limitiamo ad asserire che si ottiene una distribuzione normale, che

                               si comporta simmetricamente attorno al valore massimo  en = e * n .

 

                Il valore  en  deve quindi essere considerato come l'errore più probabile, quindi il valore di riferimento per la precisione della sequenza dei calcoli.

 

 

 

 

 

            6- - Strategie di calcolo

 

 

                La considerazione degli errori rende necessarie opportuni accorgimenti, o strategie di calcolo, almeno quando la precisione é il fattore fondamentale.

 

                Il metodo più ovvio è l'impiego di una forma di rappresentazione dei valori numerici che permetta di trattare il massimo numero di cifre esatte; i linguaggi di programmazione forniscono di norma due livelli di precisione, dette semplice e doppia ed indicate con vari nomi convenzionali per ogni linguaggio, che come già ricordato equivalgono a 6-7, oppure 13-14 cifre decimali significative, ove la indicazione 'circa' deriva dalla traduzione da decimale in binario.

 

                Molti sistemi offrono, accanto alle due standardizzate, una precisione maggiore: ne sono esempi la quadrupla precisione disponibile in ambiente VAX/VMS o la rappresentazione a 10 byte sui Personal Computer basati su microprocessore Intel. Non esistono però standard e le relative informazioni debbono essere acquisite dai manuali della particolare versione di un linguaggio implementata sul sistema.

 

                Esistono infine librerie di programmi in multipla precisione, in genere disponibili all'interno di sistemi applicativi specializzati, come i molto diffusi Mathematica, Maple, Matlab, MathCad e simili, che  sono spesso richiamabili anche da programmi scritti in linguaggi convenzionali; un utente interessato può inoltre mettere a punto proprie routine di calcolo esteso.

 

                Il ricorso a precisioni multiple non elimina però il problema degli errori di approssimazione, ma ne sposta semplicemente le frontiere. Caso per caso ci si limiterà ad adottare la rappresentazione minima sufficiente alla soluzione pratica di un particolare problema di calcolo.

 

                Oltre le possibilità offerte dalle soluzioni 'automatiche', cioè ottenibili da una particolare forma di rappresentazione dei dati in macchina, per problemi di calcolo particolarmente critici può essere  necessario fare ricorso ad una pianificazione il più possibile 'intelligente' dell'ordine delle operazioni.

 

                Si debbono cioè analizzare gli elementi strutturalmente deboli in una sequenza di calcolo, alterandola con accorgimenti mirati a prevenirli.

 

                Come si é visto, é particolarmente delicato il caso della somma, quando siano interessati due numeri di segno opposto e molto simili in valore assoluto; inoltre, una delle proprietà singolari dell'aritmetica finita è rappresentabile con la relazione:

 

  (7.6.1)                   0 ,   0                  a + b = a

 

assurda dal punto di vista dell'aritmetica ordinaria, ma che si verifica quando il salto in ordini di grandezza tra i due valori supera il massimo numero di cifre significative rappresentabili

 

                Si consideri il caso di una sommatoria, i cui termini possono essere di segno ed ordini di grandezza arbitrari: é evidentemente opportuno separare i termini positivi dai negativi per evitare il primo tipo di errore, rinviandone la trattazione all'ultima operazione, che può anche essere eseguita con un diverso livello di precisione; inoltre, i valori dei due gruppi (positivi e negativi) possono essere riordinanti, ad esempio in senso decrescente, minimizzando il rischio condizioni del tipo della (7.6.1).

 

                Queste osservazioni rendono evidente che é probabilmente impossibile fornire ricette per il controllo degli errori buone a tutti gli usi, ma che si debbono invece prendere caso per caso provvedimenti adeguati al problema che si sta trattando.