Ma il C++ è veramente preciso? Dopo aver testato il linguaggio C++ di diverse case: Visual C++ vers 6.0 Microsoft, Borland vers. 5.0, Digital mars C++ compilers, Dev C++ compilers, ho avuto risultati veramente sconfortanti riguardo la precisione di calcolo. Confrontando i risultati del benchmark Savage tra questi compilatori (che guarda caso forniscono lo stesso valore) ed i risultati di un paio di compilatori Fortran versioni libere (F World “NAG” ed F compilers “Fortran Company”) vi è un abisso. L’unico neo di questi compilatori sta nel fornire “solo” 16 decimali (precisi) su Windows e PC monoprocessore 32 bit, mentre alcuni compilatori C++ sulla stessa piattaforma sbandierano 18 decimali (vedi Borland sigh!… imprecisi). Esiste un compilatore C o C++ che che sottoposto al benchmark Savage fornisca 18 decimali esatti?

Il problema della precisione aritmetica nei calcoli in virgola mobile
non è semplice.

Innanzitutto occorre tenere presente le approssimazioni dovute alla
rappresentazione dei numeri. I numeri reali nei computer vengono espressi
mediante la cosiddetta rappresentazione in “virgola mobile”
(floating-point).
Ogni valore rappresentabile V, si esprime come:

V = M . 2E

dove M (mantissa) ed E (esponente) sono numeri, ciascuno rappresentato
da un assegnato numero di bits.
Un qualunque numero reale viene quindi approssimato con il più vicino
valore rappresentabile e l’errore commesso è tanto minore
quanto maggiore è la precisione della rappresentazione.

Il numero di bits assegnato per la mantissa determina la precisione
del numero, mentre quello assegnato per l’esponente determina il rango
dei numeri rappresentabili (ovvero il minimo e massimo valore).

Nella seguente tabella riassumo alcuni formati tipici usati per la
rappresentazione di numeri reali:

N. bits
totali
N.bits
mantissa
N.Bits
esponente
Precisione
(cifre decim.)
Rango
32 24 8 6 1.2 10-38 – 3.4 1038
64 53 11 15 2.2 10-308 – 1.8 10308
96 64 32 18 3.4 10-4932 – 1.2 104932

Nessuna operazione di un computer può avere una precisione migliore
di quella della rappresentazione numerica, anzi di solito la precisione
tende a diminuire via via che si calcolano espressioni più complesse
per un fenomeno detto “propagazione dell’errore”.

Poiché i numeri devono essere utilizzati direttamente dalle
operazioni aritmetiche all’interno del processore, la precisione
della rappresentazione
è determinata dall’architettura della CPU e non dipende
dal particolare compilatore.

Però nel caso del programma di prova citato nella domanda (Savage), la
“precisione” del risultato fornito da programmi compilati con differenti
compilatori viene valutata con un ciclo di iterazioni che ripete molte volte
il calcolo di una espressione che contiene anche alcune funzioni matematiche
(tangente, logaritmo, esponenziale, ecc.) e questa è la componente che
può dipendere dal particolare compilatore. Poiché
il linguaggio C/C++ non è solitamente utilizzato per applicazioni con particolari
esigenze di precisione numerica, molti compilatori utilizzano le librerie
matematiche standard (spesso un’unica libreria uguale per tutti) e quindi
non c’è da stupirsi se forniscono risultati identici.

Il linguaggio FORTRAN, invece, ha il suo principale campo di applicazione nei
problemi numerici e quindi i progettisti dei compilatori prestano particolare
attenzione nel realizzare librerie matematiche di massima precisione.

Per quanto riguarda l’ultima domanda non so dare indicazioni.
Ho visto in passato
applicazioni che, per risolvere problemi di precisione in programmi scritti in
C, utilizzavano chiamate a funzioni di libreria di un compilatore FORTRAN, ma
si tratta di utilizzare tecniche di programmazione non proprio ortodosse.

Per una trattazione ampia e dettagliata dei problemi discussi rimando alla
documentazione della libreria GNU C ed in particolare ai capitoli:
Floating
Point Representation Concepts

e
Mathematics.