[C- vari] Enigma approssimazioni

tulkas85
Salve, sono alle prese con un problema da cui non riesco a venirne fuori.

Ci vorrebbe qualcuno esperto con il sistema floating point.
Uso diversi linguaggi tra cui C, Fortran e Matlab.
La questione è la seguente, ho una riga di codice che dipende da una sola variabile, questa variabile è IDENTICA in tutti e tre gli ambienti sopra citati.
L'output purtroppo anche se di pochissimo, è diverso.

Per apprezzare queste differenze sono andato ad osservare le rappresentazioni esadecimali di queste variabili double.

il codice che segue è il medesimo tra tutti gli ambienti (fidatevi), le prime due righe sono quelle originali, le altre sono delle derivazioni, che dovrebbero produrre lo stesso risultato, almeno a livello matematico.

Osservate e giudicate:
(absc1 e absc2 sono dei valori double impostati che ovviamente non cambiano tra i vari casi sotto elencati )
// 1
tabsc1 = (1-absc1)/absc1;
tabsc2 = (1-absc2)/absc2;
// 2
tabsc1 = (0.5/absc1-1+0.5/absc1);
tabsc2 = (0.5/absc2-1+0.5/absc2);
// 3
tabsc1 = (1.0/absc1-1.0);
tabsc2 = (1.0/absc2-1.0);
// 4
tabsc1 = ((0.5-absc1)/absc1+0.5/absc1);
tabsc2 = ((0.5-absc2)/absc2+0.5/absc2);


valori in esadecimale di
absc1
3FE0117FD8ACBD94
absc2
3FDBDD4FCDF1D0EB

Risultati di tabsc1 e tabsc2
Compilatore C:  gcc (Codeblock)

tabsc1                       tabsc2

3FEFBA4CD894D781    3FF4BFD02B02FEDB

3FEFBA4CD894D781    3FF4BFD02B02FEDB

3FEFBA4CD894D781    3FF4BFD02B02FEDB

3FEFBA4CD894D781    3FF4BFD02B02FEDB

Compilatore Intel Visual Fortran :

3FEFBA4CD894D781    3FF4BFD02B02FEDA

3FEFBA4CD894D782    3FF4BFD02B02FEDA

3FEFBA4CD894D782    3FF4BFD02B02FEDA

3FEFBA4CD894D782    3FF4BFD02B02FEDA

Matlab :

3FEFBA4CD894D781    3FF4BFD02B02FEDA

3FEFBA4CD894D782    3FF4BFD02B02FEDA

3FEFBA4CD894D782    3FF4BFD02B02FEDA

3FEFBA4CD894D782    3FF4BFD02B02FEDA


le differenze riguardano gli ultimi 4 bit della mantissa, anzi gli ultimi due.
Quali sono i valori esatti ?? quelli di C ? o quelli degli altri 2 ambienti ?
Da notare che con il primo valore di absc1 cambiando le formule si riescono ad ottenere due risultati differenti anche in Matlab e Fortran...

Risposte
apatriarca
Direi che una differenza così bassa tra i vari risultati è più che accettabile e prevedibile visto che hai eseguito le tue operazioni in virgola mobile. Ricordati che su un computer avrai sempre a che fare con approssimazioni e nel caso delle operazioni in virgola mobile è sufficiente un diverso ordinamento delle operazioni per ottenere risultati differenti.

ZeroMemory
Fai conto che l'accuratezza di una serie di operazioni in virgola mobile dipendeda molti fattori:

1) gli stati della FPU (la parte del processore che elabora dati in virgola mobile).
questi determinano la modalità di arrotondamento e la precisione delle istruzioni divide e sqrt.

2) quante volte le variabili floating point passano dai registri della FPU alla memoria.
La FPU elabora dati a precisione estesa (ci sono tre formati floating point IEEE 754: precisione singola 32bit, doppia 64bit, estesa 80bit) e i suoi registri sono quindi di 80bit. Questo sia che le variabili nel sorgente siano float o double. L'unica differenza tra float e double è che quando le variabili nei registri tornano in memoria vengono arrotondate alla precisione con cui sono rappresentate in memoria. Quindi a 32bit se dichiarate float o 64bit se dichiarate double. riassumendo possiamo dire che l'abilità del compilatore nel gestire i registri determina anche l'accuratezza del risultato, a meno che le variabili non siano dichiarate di 80bit ("long double" in C) NB: le configurazioni di debug ricaricano spesso dalla memoria le variabili nei registri!

3) come dice apatriarca, l'ordine delle istruzioni può determinare l'accuratezza dei calcoli e la velocità. I compilatori potrebbero avere un opzione per permettergli di riordinare le istruzioni in virgola mobile.

Io proverei a dichiarare le variabili come "long double" e vedere se continuano e venirti fuori risultati diversi...non conosco però il fortran e non so quindi se è possibile. Inoltre accertati che non siano configurazioni di debug.
Comunque è del tutto normale che ci siano queste leggere discordanze.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.