Rieccoci a parlare di formati in virgola mobile e loro varianti, un argomento che iniziai ad affrontare oltre 5 anni fa (in un articolo a cui rimandiamo per una introduzione all'argomento e per la descrizione della terminologia qui utilizzata) e che si rivela una miniera ricca di spunti. In questo caso, ho voluto riesaminare tutta la questione ponendomi due obiettivi ben precisi:

1) Quali sono i valori di precisione e di esponente veramente ottimali, in grado di soddisfare praticamente tutte le esigenze concrete?

2) Come implementare un tale standard minimizzando la complessità di codifica e senza discostarsi troppo dagli standard attuali?

 La seconda domanda nasce dalla considerazione che gli affascinanti stratagemmi presentati in passato per estendere le capacità dei formati floating point attualmente in uso (ad esempio il variable exponent e altri ancora più elaborati) rischiano di aumentare il numero di operazioni che le unità logico-aritmetiche (cores) devono effettuare per maneggiare tali codifiche complesse; questo porterebbe a un inevitabile aumento nei tempi di calcolo oppure nella complessità dei circuiti (con effetti deleteri sulle performances o sui consumi della CPU/GPU).

 Partiamo sempre dallo standard più utilizzato, quello della doppia precisione a 64 bit. Come evidenziato più volte negli articoli precedenti, esso risulta avere un livello di precisione e un esponente massimo/minimo sovrabbondanti nella maggior parte delle applicazioni. Tuttavia, ci sono casi particolari in cui le sue 15 cifre significative (in verità quasi 16) possono risultare insufficienti. Ne è un esempio il recente calcolo dell'evoluzione dell'orbita dell'asteroide Bennu che, dovendo tenere conto di termini perturbativi 1018 volte più piccoli di quelli principali, ha costretto i ricercatori a ricorrere alla precisione quadrupla (128 bit), peraltro più che sovrabbondante allo scopo, dato che essa si spinge ad utilizzare 34 cifre decimali! Discorso analogo si potrebbe fare per le misure più precise di tempo, dato che i nuovi modelli di orologi atomici raggiungono una precisione relativa dell'ordine di 10-19.

 Pertanto, volendo stabilire uno standard che possa far fronte a queste situazioni estreme senza uno "spreco" di bit e quindi evitando una inutile complessità hardware o una congenita inefficienza, la soluzione ideale dovrebbe attestarsi su una precisione massima di 20 cifre decimali significative, che si traducono in una mantissa di 67-70 bit. Per quanto riguarda invece l'esponente, è davvero difficile immaginare situazioni in cui siano necessari valori che vadano oltre l'intervallo (-100 ÷ +100) ma, per non creare un sistema che abbia prestazioni inferiori a quello già in uso, la scelta ricade sugli 11 bit di esponente, capaci di garantire esponenti decimali superiori a 300 in valore assoluto.

 La scelta a questo punto è quasi obbligata e, limitandoci a parole multiple di 16 bit, ricade su un sistema floating di 80 bit, costituito appunto da 11 bit di esponente e 69 bit di mantissa; questi ultimi garantiscono una precisione di 20,77 cifre decimali (facendo naturalmente ricorso all'hidden bit), dunque in linea con quanto detto prima, cioè 20 cifre significative con abbondante margine di arrotondamento.

 Tuttavia, anche in questo caso presento una opzione "extended" (la "e" finale del titolo) per implementare l'uso di esponenti ancora più grandi, a scapito di una ridotta precisione nella mantissa. Tale precisione, però, non deve comunque scendere significativamente al di sotto dello standard a doppia precisione, per non inficiare la superiorità del nuovo sistema su tutti i fronti; questo significa avere una mantissa di 52 bit (e non 53 come nel FP64 standard, dato che 15,65 decimali sono sufficienti mentre 15,95 sono inutilmente vicini a 16).  Inoltre, per mantenere un certo rigore nella gestione della precisione, è preferibile che tutti i risultati numerici mantengano sempre traccia di un eventuale ricorso a questa modalità a "esponente esteso" e "precisione ridotta". Questa sorta di ereditarietà della precisione si ottiene con una ridondanza sugli esponenti, ovvero riproducendo anche i valori con esponente basso, già abbracciati dalla modalità a precisione piena. Alla fine, questo permetterà di distinguere i risultati a precisione più bassa da quelli con 20 cifre realmente significative; stiamo parlando di una eventualità che, nell'utilizzo normale, non si presenterà praticamente mai perchè presuppone il calcolo di quantità insolitamente piccole o grandi!

 Ecco dunque due possibili alternative per il nuovo standard "FP80e", la cui codifica è essenzialmente strutturata nei seguenti 3 domini, senza necessariamente ricorrere ai numeri "denormalizzati", che non avrebbero molto senso in questo ambito.

01a) esponente binario compreso tra -1022 e +1022 (2045 valori): numeri normalizzati (con hidden bit) a piena precisione, con 69 bit di mantissa ed esponente decimale che va da -307 a +307.

01b) esponente binario pari a -1023 o +1023: numeri a precisione "ridotta", con 52 bit di mantissa e i rimanenti 17 bit che codificano un esponente decimale compreso tra -19728 e +19728; eventualmente, all'estremo inferiore dell'esponente possono essere associati numeri de-normalizzati piccolissimi (il più piccolo valore non nullo sarà dell'ordine di 10-19744).

01c) esponente binario pari a +1024 (valore massimo): valori ±∞ e codici NaN (ben 5.9·1020 combinazioni possibili)

 La seconda alternativa (ma ce ne potrebbero essere altre 22 intermedie) prevede invece di abbassare leggermente l'esponente massimo in piena precisione, creando molte più combinazioni a vantaggio di esponenti ancora più grandi in valore assoluto, quando si lavora in precisione ridotta:

24a) esponente binario compreso tra -999 e +999 (1999 valori): numeri normalizzati (con hidden bit) a piena precisione, con 69 bit di mantissa ed esponente che va da -300 a +300.

24b) esponente binario compreso tra -1023 e -1000 oppure tra +1000 e +1023 (48 combinazioni in tutto): numeri a precisione "ridotta", con 52 bit di mantissa e i rimanenti 17 bit che codificano un esponente compreso tra -473479 e +473479; eventualmente, all'estremo inferiore dell'esponente possono essere associati numeri de-normalizzati piccolissimi (il più piccolo valore non nullo sarà dell'ordine di 10-473485).

24c) esponente binario pari a +1024 (valore massimo): valori ±∞ e codici NaN (ben 5.9·1020 combinazioni possibili)

  Quest'ultima opzione è quella riportata nella tabella dei possibili formati Floating attuali e proposti, visibile in apertura articolo; i valori tra parentesi quadre, naturalmente, sono riferiti all'opzione con esponente espanso e precisione ridotta.

 

Considerazione finale (aggiunta nel dicembre 2021)

  Dal punto di vista pratico, non è realmente necessario ricorrere all' opzione "extended" per incrementare l'esponente oltre la regione ±307, ben poco sfruttabile. Un formato classico FPF con 69+11 bit dovrebbe adattarsi praticamente a qualsiasi utilizzo "normale". Al limite, volendo eccedere a tutti i costi il formato in doppia precisione senza ricorrere alla complicazione di annidare due diversi formati, si potrebbe puntare in alternativa su un formato FP88 semplice, che assegna 72 bit alla mantissa (con una ulteriore cifra decimale significativa) e 16 bit all'esponente, sfiorando quindi i 10000 in valore assoluto.