2009-07-20 5 views
5

Cercando di eseguire il porting del codice java su C++, mi sono imbattuto in qualche comportamento strano. Non riesco a ottenere una doppia aggiunta al lavoro (anche se l'opzione compiler/fp: strict che significa "corretta" matematica in virgola mobile è impostata in Visual Studio 2008).Perché i doppi vengono aggiunti in modo non corretto in un progetto specifico di Visual Studio 2008?

double a = 0.4; 
/* a: 0.40000000000000002, correct */ 

double b = 0.0 + 0.4; 
/* b: 0.40000000596046448, incorrect 
(0 + 0.4 is the same). It's not even close to correct. */ 

double c = 0; 
float f = 0.4f; 
c += f; 
/* c: 0.40000000596046448 too */ 

In un diverso progetto di test ho istituito funziona benissimo (/ fp: si comporta severe in base alle IEEE754).

Utilizzo di Visual Studio 2008 (standard) con Nessuna ottimizzazione e FP: strict.

Qualche idea? Sta davvero troncando ai galleggianti? Questo progetto ha davvero bisogno dello stesso comportamento su entrambi i lati Java e C++. Ho ottenuto tutti i valori leggendo dalla finestra di debug in VC++.

Soluzione: _fpreset(); // L'idea di Barry Kelly l'ha risolta. Una libreria stava impostando la precisione FP su un valore basso.

+2

È possibile pubblicare un piccolo programma di test completo con la riga di comando esatta utilizzata per compilare (vedere la finestra di output, ecc.), Che dimostra il problema? L'unico modo che posso riprodurre è usando 0.0f + 0.4f invece. –

+0

Possiamo presumere che tu sia a conoscenza dell'imprecisione dei tipi a virgola mobile? Essere precisi con 7 posizioni decimali è generalmente considerato ok poiché la precisione di stampa predefinita è 6. –

+0

@Evan, il suo esempio è più alto di quello che sarebbe spiegato dall'imprecisione in virgola mobile. – Kevin

risposta

8

L'unica cosa a cui riesco a pensare è forse il collegamento a una libreria o una DLL che ha modificato la precisione della CPU tramite la parola di controllo.

Hai provato a chiamare _fpreset() da float.h prima del calcolo problematico?

+0

Deve essere qualcosa lungo quelle linee, ma è 0.0 + 0.4 anche un calcolo? Non può essere valutato al momento della compilazione? Il controllo del disassemblaggio potrebbe stabilire se la modalità float di runtime ha qualcosa a che fare con esso o se qualcosa è andato storto in fase di compilazione. –

+0

Certo che può essere, ma se fosse così semplice, sarebbe facile da riprodurre, no? –

+0

Non so, forse qualcos'altro nel progetto sta specificando/fp: stupido o equivalente. Il mio preferito personale sarebbe un file sorgente non terminato con una nuova riga e quindi il programma ha un comportamento indefinito, anche se non nutro molte speranze di vederlo causare un bug in natura ... –

3

Sì, è certamente troncato per galleggiare. Ottengo lo stesso valore di stampa float f = 0.4 come nel caso "impreciso". Prova:

double b = 0.0 + (double) 0.4; 

La domanda è quindi perché sta troncando a galleggiare. Non ci sono scuse nello standard per il trattamento di 0.0 + 0.4 come espressione a precisione singola, poiché i valori letterali in virgola mobile sono a precisione doppia, a meno che non abbiano un suffisso per dire altrimenti.

Quindi qualcosa deve interferire con le impostazioni, ma non ho idea di cosa.

Problemi correlati