Il problema.C++ perdita di precisione in virgola mobile: 3015/0.00025298219406977296
Compilatore Microsoft Visual C++ 2005, 32 bit windows xp sp3, amd 64 x2 cpu.
Codice:
double a = 3015.0;
double b = 0.00025298219406977296;
//*((unsigned __int64*)(&a)) == 0x40a78e0000000000
//*((unsigned __int64*)(&b)) == 0x3f30945640000000
double f = a/b;//3015/0.00025298219406977296;
il risultato del calcolo (cioè "f") è 11917835,000 milioni (((unsigned __int64) (& f)) == 0x4166bb4160000000) anche se dovrebbe essere 11.917.834,814,763514 millions (cioè ((non firmato __int64) (& f)) == 0x4166bb415a128aef).
I.e. la parte frazionaria è persa.
Sfortunatamente, ho bisogno che la parte frazionaria sia corretta.
Domande:
1) Perché succede?
2) Come posso risolvere il problema?
Ulteriori informazioni:
0) Il risultato è preso direttamente dalla finestra "guardare" (che non è stato stampato, e non mi ha dimenticato di impostare la stampa di precisione). Ho anche fornito un dump esadecimale di variabile in virgola mobile, quindi sono assolutamente sicuro del risultato del calcolo.
1) Lo smontaggio f = a/b è:
fld qword ptr [a]
fdiv qword ptr [b]
fstp qword ptr [f]
2) f = 3015/,00025298219406977296; rendimenti risultato corretto (f == 11.917.834,814,763514 millions, ((unsigned __int64) (& f)) == 0x4166bb415a128aef), ma sembra che in questo caso è semplicemente risultato calcolato durante fase di compilazione:
fld qword ptr [[email protected] (828EA0h)]
fstp qword ptr [f]
Così , come posso risolvere questo problema?
P.S. Ho trovato una soluzione temporanea (ho bisogno solo di una parte frazionaria della divisione, quindi uso semplicemente f = fmod (a/b)/b al momento), ma mi piacerebbe comunque sapere come risolvere correttamente questo problema - double la precisione dovrebbe essere di 16 cifre decimali, quindi questo calcolo non dovrebbe causare problemi.
Questa è una risposta corretta. Il programma utilizza Direct3D e, ovviamente, il calcolo avviene dopo la creazione del dispositivo. La cosa divertente è che sapevo di D3D che regola la precisione della FPU, ma me ne sono completamente dimenticato, perché non ho visto questo errore negli ultimi anni. Problema risolto. – SigTerm
Quale contrassegno deve essere utilizzato durante la creazione del dispositivo? Lo stesso problema esiste con Direct2D? – dalle