Il metodo che metterà fine agli errori di approssimazione in informatica

Addio numeri in virgola mobile?
27 aprile 2016, 2:38pm

Anche per i più scarsi in matematica, un numero decimale non è un ostacolo insormontabile. Potrei dirvi, chessò, 33,33 e non sarebbe necessario nessun contorsionismo mentale per capirlo (non voglio suggerire che tu, lettore particolare, sia molto scarso in matematica, ma cerca di stare al gioco). Insomma, sono 33 cose, più 0.33 di un'altra cosa; quasi un terzo della trentaquattresima cosa. Non è più difficile di così.

I computer, però, intrattengono una relazione delicata e complessa con le cifre decimali. I numeri interi sono facili, perché è facile rappresentare un intero in base 10 come numero binario (in base 2). Con 32 bits, o 32 cifre, possiamo rappresentare un'enorme varietà di interi (solitamente integers o ints, in informatica), fino a 2147483647. Di solito sono più che sufficienti. Il problema di sommare valori decimali è che diventa necessario avere un modo per indicare dove si trovi esattamente la virgola all'interno di una sequenza di cifre e questa posizione cambia da numero a numero.

In informatica un numero con una parte decimale e il corrispondente valore in frazione sono rappresentati dal tipo "virgola mobile" (float). Per un numero in virgola mobile a 32 bit emerge che abbiamo realmente a disposizione solo 23 cifre binarie per rappresentare il numero, mentre le altre saranno necessarie a rappresentare la posizione della virgola (sotto forma di esponente, in notazione scientifica).

Il problema non dipende tanto dal limitato range di valori possibili, quanto da limitazioni fondamentali sulla precisione che può essere ottenuta. È possibile verificarlo facilmente considerando un numero arbitrariamente grande e spostando la virgola al suo interno. Più grande diventa il numero—e con questo il numero di cifre alla sinistra della virgola—meno cifre saranno disponibili per rappresentare la parte decimale.

John Gustafson, un informatico specializzato in high-performance computing e la persona ce ha dato il nome alla legge di Gustafson, ha proposto una soluzione per questa fonte inesauribile di errore (si legga: imprecisione). Ha battezzato la sua nuova rappresentazione "unum," che sta per numero universale.

La differenza fondamentale è che l'unum permette ai vari "campi" che compongono la rappresentazione binaria di un numero in virgola mobile di espandersi e contrarsi in base ala precisione richiesta. I valori d'esponente richiesti per scalare la maggior parte dei numeri decimali (nel senso di determinare le posizioni dei loro punti decimali) sono generalmente molto minori di quelli rappresentabili con cinque bit, tanti quanti ne sono allocati in un numero a 32 bit, ma lo standard odierno è fissato per lo scenario peggiore. Se il campo "esponente" è in grado di restringersi, guadagniamo cifre che possiamo usare per rappresentare davvero il numero, il che è sempre bene.

Ecco il numero di Avogadro, 6.022×1023, nei due modi:

"Un unum presenta tre campi addizionali che rendono il numero autodescrittivo," spiega Gustafson in un'intervista concessa alla rivista Ubiquity di ACM. "Abbiamo l'ubit che specifica se il numero sia esatto o compreso tra valori esatti, quello che segna la dimensione dell'esponente in bit e quello che segna la dimensione della mantissa. Quindi non solo la virgola è mobile, ma anche il numero di cifre significative può variare."

Esiste, poi, un ulteriore problema di approssimazione riguardo ai numeri in virgola mobile; probabilmente è più difficile da intuire, ma Gustafson ne da buon esempio.

Si immagini di avere due numeri molto vicini tra loro, per esempio 1.000.000,7 e 1.000.000,6. Sottrarre il secondo al primo ci da ,1000000. Il problema con ,1000000 è che sembra proprio di avere sei cifre significative alla destra dell'1, quando in realtà non abbiamo idea di cosa ci sia in quelle cifre segnate come zeri. Sono apparse solo dopo la sottrazione. Nei due numeri originali, questa informazione si troverebbe da qualche parte alla destra delle cifre 6 e 7, un territorio inesplorato. Nei due numeri originali, questa informazione si troverebbe da qualche parte alla destra delle cifre 6 e 7, un territorio inesplorato.

E quindi? Quindi il problema emerge quando eseguiamo un calcolo con il nostro nuovo numero. Per esempio, se andiamo a sommare 1,0×10-12 otterremo ,1000001×10-6. Che potrebbe sembrare giusto (sommare ,1 a ,000000000001 e ottenere ,10000000001), ma no. Perché non avevamo nessuna reale informazione di cosa ci fosse alla destra di 1 in ,1. Abbiamo solo costretto il computer a pensarla così. L'unica cosa che possiamo fare con il secondo, più piccolo, numero è prenderlo e cestinarlo. È oltre la nostra precisione.

L'utilità di avere un campo dedicato a precisare se il nostro numero sia esatto o un'approssimazione è proprio questa. Se il computer sa che è esatto e gli zeri significano precisamente zero e non un generico non-lo-so, allora possiamo procedere coi calcoli. In caso contrario non possiamo.

L'intervista su Ubiquity è piuttosto profonda, ma assolutamente consigliata se riuscite a seguire la matematica coinvolta e siete interessati a saperne di più su come i computer rappresentino l'informazione (spesso malamente). Unum, nel mentre, sta ottenendo riscontri.

"Ero alla conferenza Supercomputing ad Austin, in Texas, ed ero sorpreso nel constatare l'interesse sorto intorno a unum e gli sforzi software di implementarlo," ha detto Gustafson. "Il porting Python è già pronto e diversi gruppi stanno lavorando a quello C. Dal momento che il linguaggio Julia è particolarmente efficiente nell'integrare nuovi tipi senza sacrificare la velocità, molte persone stanno lavorando a un porting Julia, compresi i ricercatori del MIT che hanno inventato il linguaggio. Sono a conoscenza di un progetto per includere unum in Java e D, il successore di C++."