Questo problema non è causato dalla conversione da lunga doppia a doppia. Potrebbe essere dovuto a inaccuratezza nella routine sin
nella libreria matematica.
L'istruzione fsin
viene specificata per produrre un risultato entro 1 ULP (nel formato doppio lungo) per gli operandi all'interno del suo intervallo (in base a Intel 64 e IA-32 Architectures Software Developer's Manual, ottobre 2011, volume 1, 8.3.10), in modalità round to to nearest. In un Intel Core i7, fsin
del valore dell'interrogante, -5.07121364272633190495298549649305641651153564453125 o -0x1.448ec3aaa278dp + 2, produce 0xe.fb206c69b0ba402p-4. Possiamo facilmente vedere da questo esadecimale che gli ultimi 11 bit sono 100 0000 0010. Questi sono i bit che verranno arrotondati durante la conversione dal doppio lungo. Se sono superiori a 100 0000 0000, il numero verrà arrotondato per eccesso. Sono più grandi Pertanto, il risultato della conversione di questo doppio valore lungo in double è 0xe.fb206c69b0ba8p-4, che equivale a 0x1.df640d8d36175p-1 e 0.93631021832247418590355891865328885614871978759765625. Si noti inoltre che, anche se il risultato fosse inferiore di un ULP, gli ultimi 11 bit sarebbero comunque superiori a 100 0000 0000 e andrebbero comunque arrotondati. Pertanto questo risultato non dovrebbe variare su CPU Intel conformi alla documentazione di cui sopra.
Confronta questo per calcolare direttamente un seno a doppia precisione, utilizzando una routine ideale che produce risultati correttamente arrotondati. Il seno del valore è approssimativamente 0.93631021832247413051857150785044253634581268961333520518023697738674775240815140702992025520721336793516756640679315765619707343171517531053811196321335899848286682535203710849065933755262347468763562 (calcolato con Maple 10). Il doppio più vicino a questo è 0x1.df640d8d36175p-1. È lo stesso valore che abbiamo ottenuto convertendo il risultato fsin
in double.
Pertanto, la discrepanza non è causata dalla conversione del lungo da doppio a doppio; la conversione del doppio risultato lungo fsin
in raddoppio produce esattamente lo stesso risultato di una routine sin
a precisione doppia ideale.
Non abbiamo una specifica per la precisione della routine sin
utilizzata dal pacchetto Visual Studio del questionario. Nelle biblioteche commerciali è comune la possibilità di errori di 1 ULP o diversi ULP. Osservare quanto vicino il seno è in un punto in cui il valore di precisione doppia è arrotondato: È .498864 ULP (doppia precisione ULP) lontano da un doppio, quindi è 0,100366 ULP lontano dal punto in cui l'arrotondamento cambia. Pertanto, anche una minima inesattezza nella routine sin
causerà il ritorno 0x1.df640d8d36174p-1 anziché il più vicino 0x1.df640d8d36175p-1.
Pertanto, suppongo che l'origine della discrepanza sia un'imprecisione molto piccola nella routine sin
.
fonte
2012-09-01 12:23:22
Un'operazione può essere eseguita interamente nei registri a virgola mobile. L'altro comporta una perdita di precisione quando il registro a 80 bit viene scritto in un indirizzo di memoria a 64 bit. La documentazione FSTP dice che "quando si memorizza il valore in memoria, il valore viene convertito in formato reale singolo o doppio". –
L'approccio 'fsin' utilizza la FPU x87 con precisione a 80 bit, l'implementazione di' sin' in MSVC (sto usando 2010) sembra utilizzare SSE con i suoi registri xmm * a 128 bit. (Vedi anche [questa domanda] (http://stackoverflow.com/questions/2284860/how-does-c-compute-sin-and-other-math-functions).) – DCoder