Sto utilizzando .NET 2.0 con PlatformTarget x64 e x86. Sto dando a Math.Exp lo stesso numero di input e restituisce risultati diversi su entrambe le piattaforme.Perché Math.Exp fornisce risultati diversi tra 32-bit e 64-bit, con lo stesso input, stesso hardware
MSDN dice che non si può contare su un letterale/Doppia analizzato per rappresentare lo stesso numero tra le piattaforme, ma penso che il mio uso di Int64BitsToDouble sotto evita questo problema e garantisce lo stesso ingresso per math.exp su entrambe le piattaforme.
La mia domanda è perché i risultati sono diversi? Avrei pensato che:
- l'ingresso viene memorizzato nello stesso modo (doppia/64-bit di precisione)
- dell'FPU farebbe gli stessi calcoli indipendentemente bitness processore
- l'uscita viene memorizzata in allo stesso modo
So che non dovrei confrontare i numeri in virgola mobile dopo la cifra 15/17 in generale, ma sono confuso sull'incoerenza qui con quella che sembra la stessa operazione sullo stesso hardware.
Qualcuno sa cosa sta succedendo sotto il cofano?
double d = BitConverter.Int64BitsToDouble(-4648784593573222648L); // same as Double.Parse("-0.0068846153846153849") but with no concern about losing digits in conversion
Debug.Assert(d.ToString("G17") == "-0.0068846153846153849"
&& BitConverter.DoubleToInt64Bits(d) == -4648784593573222648L); // true on both 32 & 64 bit
double exp = Math.Exp(d);
Console.WriteLine("{0:G17} = {1}", exp, BitConverter.DoubleToInt64Bits(exp));
// 64-bit: 0.99313902928727449 = 4607120620669726947
// 32-bit: 0.9931390292872746 = 4607120620669726948
I risultati sono coerenti su entrambe le piattaforme con JIT attivato o disattivato.
[Edit]
io non sono del tutto soddisfatto delle risposte di seguito ecco alcuni dettagli della mia ricerca.
http://www.manicai.net/comp/debugging/fpudiff/ dice che:
Così 32 bit utilizza registri FPU 80 bit, 64 bit utilizza 128 bit SSE registri.
E la CLI standard dice che doppie possono essere rappresentate con maggiore precisione se l'hardware lo supporta:
[Razionale: Questo design permette la CLI di scegliere una rappresentazione ad alte prestazioni specifico per la piattaforma per numeri a virgola mobile fino a quando non vengono collocati in posizioni di memoria. Ad esempio, potrebbe essere in grado di lasciare le variabili in virgola mobile in registri hardware che forniscono maggiore precisione di quanto richiesto da un utente. Allo Partition I 69 allo stesso tempo, i generatori CIL possono forzare le operazioni a rispettare le regole specifiche della lingua per le rappresentazioni tramite l'uso delle istruzioni di conversione. fine logica]
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf (12.1.3 Gestione dei tipi di dati a virgola mobile)
credo che questo è quello che sta succedendo qui, perché i risultati diversi dopo di doppie standard di 15 cifre di precisione. Il risultato Math.Exp a 64 bit è più preciso (ha una cifra in più) perché internamente a 64 bit .NET utilizza un registro FPU con maggiore precisione rispetto al registro FPU utilizzato da .NET a 32 bit.
+1 Interessante. Vedo gli stessi identici sintomi sulla mia macchina e il passaggio da x86 a anycpu cambia l'output. – sisve
Il tuo paragrafo finale non è corretto. La versione a 32 bit sarà ** più corretta ** perché utilizza la FPU di precisione estesa x87 a 80 bit, mentre la versione a 64 bit utilizzerà la SSE2 più veloce e più coerente. –
Possibile duplicato di [Differenza in aritmetica in virgola mobile tra x86 e x64] (http://stackoverflow.com/questions/22710272/difference-in-floating-point-arithmetics-between-x86-and-x64) –