Errare (non) è (solo) umano

La calcolatrice elettronica pisana al museo.

I precedenti post del collega Juhan e di Zar mi hanno ricordato i bei vecchi tempi di quando ero uno studente pischello a Ingegneria a Pisa (nei lontanissimi anni ’90) e tra le visite a piazza dei Miracoli in cerca di belle turiste straniere (sempre andate male) e rovinose partite di calcetto (la nostra squadra si chiamava “Inseminators”, ma non finì il campionato tanto bene), ero costretto a studiare il corso di “Calcolo Numerico”. Lo teneva il prof. Lombardi, uno di quelli che  partecipò alla costruzione della mitica CEP (Calcolatrice Elettronica Pisana, ma guardate anche qui), che potete oggi ammirare in un museo sempre in quel di Pisa. I tempi del prof. Lombardi dovevano essere migliori dei miei, perché l’Italia era all’avanguardia nella ricerca sull’elettronica e l’informatica, l’Olivetti di Adriano Olivetti era una gran bella azienda, e gli italiani erano pieni di belle speranze. Come avrete capito il prof. Lombardi non era giovanissimo, e si perdeva spesso (almeno una volta a lezione) nei ricordi del bel tempo che fu. Ma non divaghiamo troppo.

Il corso di Calcolo Numerico, tenuto ancora oggi ed obbligatorio in un certo numero di corsi di laurea a Ingegneria, insegna metodi numerici per il calcolo: per esempio a come risolvere numericamente equazioni, sistemi di equazioni, fare integrali, ecc. Uno dei primi argomenti è il trattamento dell’errore di rappresentazione nei numeri.  Lungi da me rifare qui il corso: vorrei solo farvi notare alcune cosine, che magari vi faranno capire come non sia poi così facile far fare i calcoli a un computer. Dato che non mi ricordo più tanto bene, magari dirò qualche cappellata e allora mi correggerete (spero).

Come tutti saprete, non tutti i numeri reali sono rappresentabili con esattezza. In particolare, ogni numero all’interno del nostro amato PC è rappresentato con un numero finito di bit. La rappresentazione standard per numeri con la virgola è la rappresentazione in virgola mobile. Praticamente ogni numero viene rappresentato come una mantissa e un esponente. Ad esempio, se devo rappresentare il numero 0.00002 il ‘puter lo rappresenta come 0.2 \cdot 10^{-4}. Un certo numero di cifre sono riservate alla mantissa, il resto sono riservate all’esponente. Per fare gli esempi semplici, supporrò che 5 cifre decimali siano dedicate alla mantissa, e 2 cifre decimali all’esponente. Si può quindi arrivare in valore assoluto da 0.00001 \cdot 10^{-99} a 0.99999 \cdot 10^{99}.

Quindi, per seguire l’esempio classico, se devo rappresentare \frac{1}{3} posso farlo solo con un certo errore, nel caso in questione l’errore sarà 0.00000333 \ldots. Qual’è l’errore massimo di rappresentazione che posso avere su un qualunque numero? E’ chiaro che se il numero che devo rappresentare non è troppo grande (cioè maggiore di 10^{99}) né troppo piccolo (cioè minore di 0.00001 \cdot 10^{-99}), l’errore si ha solo sulla mantissa. Cioè, se indico con r la rappresentazione del numero x, si ha l’errore assoluto

E = |x - r|.

Adesso scrivo x e r come mantissa ed esponente, utilizzando lo stesso esponente p:

x = m \cdot 10^{p} e r = m^\prime \cdot 10^{p},

dove ho indicato con m la mantissa esatta e con m^{\prime} la sua rappresentazione. Poi, invece di calcolare l’errore assoluto, calcolo l’errore relativo, cioè in percentuale sul numero:

\delta = \frac{|x - r|}{x} = \frac{|m - m^{\prime}| 10^{p}}{m 10^{p}} = \frac{|m - m^{\prime}|}{m}.

Supponendo che facciate i calcoli facendo un’arrotondamento (e non un troncamento), la differenza |m - m^{\prime}| dipenderà da quante cifre utilizzate per rappresentare la mantissa; nel caso ad esempio di 5 cifre, tale errore al massimo sarà pari a 0.5 \cdot 10^{-5}, e nel caso peggiore (m più grande possibile) avremo appunto \delta = |0.5 \cdot 10^{-5}|. Quindi, possiamo scrivere che:

|x (1 -\delta)| \leq |r| \leq |x (1 +\delta)|,

ovvero l’errore massimo relativo che posso fare nel rappresentare il numero x è appunto pari a \delta.

Fin qui è stata matematica noiosa e con un sacco di simboli (e probabilmente a questo punto il 99% dei lettori avrà smesso di leggere, e saremo rimasti in pochi, al limite sarò rimasto da solo. Va beh, meglio pochi ma buoni!). Era roba preparatoria, adesso però viene il bello: ci resta da vedere cosa succede quando facciamo dei calcoli. Analizzerò due operazioni: somma e moltiplicazione.

Supponiamo di dover sommare x e y. Le loro rappresentazioni sono \alpha e \beta. Naturalmente, quando facciamo i calcoli sul PC, invece di sommare x+y, sommiamo \alpha + \beta. Qual’è il massimo errore relativo sulla somma? Vediamo di fare i calcoli per bene, e consideriamo prima il caso in cui x e y abbiano lo stesso segno (per esempio positivo):

\frac{|\alpha + \beta - (x+y)|}{(x+y)} \leq \frac{(x+y)(1+\delta) - (x+y)}{(x+y)} = \delta

Ovvero, l’errore relativo sulla somma è lo stesso che l’errore sui termini originali. Bene, siamo confortati, possiamo sommare numeri senza paura di perdere precisione! O no? Aspettate, ci resta da vedere l’altro caso. Supponiamo che due termini x e y hanno segno diverso. Per semplificare i calcoli  supponiamo il primo sia positivo e il secondo negativo, e inoltre che il primo sia maggiore del secondo. Ecco come calcolare l’errore:

\frac{|\alpha + \beta - (x+y)|}{x+y} = \frac{|(\alpha - x) + (\beta - y)|}{x+y} \leq \frac{|\delta x - \delta y|}{x+y} = \frac{|\delta|(x-y)}{x+y}

Purtroppo è successa una cosa non molto simpatica. Se x e y hanno segno diverso e sono simili fra di loro, l’errore relativo può aumentare e di molto. Infatti, al denominatore avremo una quantità piccola mentre al numeratore una quantità grande (ricordatevi che x è positivo e y è negativo!). Ad esempio: se prendiamo i numeri 5.02 e -5.01, ognuno dei quali con un errore assoluto massimo di 0.00001, la somma sarà 0.1, con un errore massimo di 0.00002. Però 0.1 è adesso circa 500 volte più grande di 5.01, e quindi l’errore è relativamente più grande sul risultato di quanto non fosse sui numeri originali!

Insomma, non si può neanche sommare in pace! Ma se ci pensate è giusto che sia così. Se sottraete due rappresentazioni uguali, come si fa a sapere se la differenza originale fa zero oppure no? In percentuale potreste anche fare il 100% o il 1000% di errore! Va bene, basta saperlo, e tenerne conto opportunamente quando andate a fare i calcoli.

Vediamo adesso la moltiplicazione e speriamo ci vada meglio. L’errore si esprime come:

\frac{\alpha\beta - xy}{xy}

Adesso proviamo a fare un po’ di magie algebriche:

\frac{\alpha\beta - xy}{xy} = \frac{\alpha\beta - \alpha y + \alpha y - xy}{xy}= \frac{\alpha (\beta - y) + y (\alpha - x)}{xy} =

= \frac{\alpha(\beta-y) + x(\beta-y) - x(\beta-y)+y(\alpha - x)}{xy} = \frac{(\alpha-x)(\beta-y) + x(\beta-y) + y(\alpha-x)}{xy}

Osserviamo il primo termine della somma a numeratore: è il prodotto degli errori assoluti fra i due numeri. Se ad esempio gli errori sono entrambi 10^{-5}, il loro prodotto è molto più piccolo: 10^{-10}. Insomma, fidatevi, lo possiamo trascurare. Quindi:

\frac{\alpha\beta - xy}{xy} \approx \frac{\beta-y}{y} + \frac{\alpha-x}{x}.

Insomma, l’errore relativo risultante è la somma dei due errori relativi. Qundi, ogni volta che moltiplichiamo due numeri con lo stesso errore relativo, l’errore risultante raddoppia!

Immaginate di avere un numero con un errore relativo di 2^{-23} (ovvero circa 10^{-7}, e immaginate di elevarlo alla ventesima potenza (come nell’equazione di Zar). L’errore relativo sarà circa 20 volte superiore ovvero 20 \cdot 2^{-23}, ovvero, ovvero circa 2 \cdot 10^{-6}. Ci siamo mangiati un po’ di precisione, ma neanche poi tanta.

Voglio mettere un attimo a fuoco queste cose: non si scappa da questi problemi. Essi hanno a che fare con due fatti non facilmente eliminabili:

1) la precisione nella rappresentazione dei numeri reali all’interno dei calcolatori

2) proprietà matematiche indipendenti dall’esistenza o meno dei calcolatori.

In parole povere: gli ingegneri devono rassegnarsi: se hanno da fare un calcolo complicato devono analizzare l’algoritmo cercando di eliminare il più possibile le operazioni inutili, operando semplificazioni a priori, usando formule invece di calcoli iterativi ogni volta che è possibile. Insomma, non possiamo dare niente per scontato, neanche avendo a disposizione una bella e potente macchina di calcolo.

(siete arrivati fino a qui? complimenti per la pazienza!)

Posta un commento o usa questo indirizzo per il trackback.

Commenti

  • juhan  Il 26 giugno 2011 alle 11:11

    Dr.prof. che sudata!
    Me lo sono letto per benino mentre tutti sono al mare e io sto facendo un back-up come si deve prima di installare Natty. Ecco se adesso uno va a vedere il link al mio post ci viene uno s-cioppone (o mi s-cancella dal set dei raziocinanti): per cui ritiro quanto ho detto su π; non è vero che alle volte lo approssimo a 3 e meno che mai a 1. Davvero.

    O stiamo parlando di due cose diverse? Sì, io credo di sì, anche perché c’è ing. e ing. o meglio campi diversi di applicazioni.
    Comunque bello che ogni tanto ci sia un post serio e rigoroso. E sono sicuro che tutti arriveranno alla fine –figurati che leggono i miei 😉
    E se questi sono solo ricordi che memoria! o ti piaceva quel corso? 8)

    Andando decisamente OT: le formule e LaTeX (e LyX), mi sembra che sia un argomento da affrontare, ne è convinto anche il Peppe Liberti.

    • glipari  Il 26 giugno 2011 alle 11:18

      Eh, il mare è ancora lontano per me! Beati quelli che ci vanno.
      Il corso non è che me lo ricordi tanto bene, infatti ho faticato un bel po’ per ritirare fuori i due risultatini che ho presentato!

      Comunque, l’approssimazione va bene, e ci mancherebbe: non se ne può fare a meno! Solo non ci si può aspettare che uno metta dei numeri dentro un calcolatore e questo tiri fuori IL Risultato, con la maiuscola!

      E si capisce anche perché il FORTRAN sia ancora vivo: ci sono tante di quelle librerie matematiche ben fatte per risolvere ad esempio equazioni differenziali, che semplicemente i fisici preferiscono riutilizzarle, piuttosto che riscriversi tutto su un altro linguaggio!

      Per le formule e il LaTeX: ahimè, è un problema anche troppo sentito da queste parti! Speriamo che si decidano quantomeno a implementare lo standard MathML… sarebbe già un grandissimo passo avanti!

  • Rodja  Il 26 giugno 2011 alle 11:31

    Ecco le dispense del corso che fanno adesso
    http://users.dma.unipi.it/ghelardoni/libro/capitoli.html

    • glipari  Il 26 giugno 2011 alle 11:39

      Grazie Rodja per il link! (figurati, io ho il libro del Ghelardoni di più di 15 anni fa, quando non “esisteva” il LaTeX (!) e i simboli erano difficili da leggere con i normali caratteri tipografici)

      Il trattamento in questione è nel capitolo 1, nelle sezioni 1.3 e 1.4, dove ci sono i risultati anche per le altre operazioni.

  • glipari  Il 26 giugno 2011 alle 12:01

    Beh, naturalmente avevo scritto una cappellata: nell’elevare a potenza, l’errore si somma: elevando alla ventisima, l’errore relativo è “solo” venti volte superiore a quello originale. Ho corretto, spero sia l’unico errore che ho fatto!

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: