Por que o Math.Exp fornece resultados diferentes entre 32 e 64 bits, com a mesma entrada e o mesmo hardware

Estou usando o .NET 2.0 com PlatformTarget x64 e x86. Estou dando ao Math.Exp o mesmo número de entrada e ele retorna resultados diferentes em qualquer plataforma.

O MSDN diz que você não pode confiar em um duplo literal / analisado para representar o mesmo número entre plataformas, mas acho que meu uso do Int64BitsToDouble abaixo evita esse problema e garante a mesma entrada para o Math.Exp em ambas as plataformas.

Minha pergunta é por que os resultados são diferentes? Eu teria pensado que:

a entrada é armazenada da mesma maneira (precisão dupla / 64 bits)a FPU faria os mesmos cálculos, independentemente da experiência do processadora saída é armazenada da mesma maneira

Sei que não devo comparar números de ponto flutuante após o dígito 15/17 em geral, mas estou confuso sobre a inconsistência aqui com o que parece ser a mesma operação no mesmo hardware.

Alguém sabe o que está acontecendo sob o capô?

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

Os resultados são consistentes nas duas plataformas com o JIT ativado ou desativado.

[Editar]

Não estou completamente satisfeito com as respostas abaixo, então aqui estão mais alguns detalhes da minha pesquisa.

http://www.manicai.net/comp/debugging/fpudiff/ diz que:

Portanto, 32 bits estão usando os registros FPU de 80 bits, 64 bits estão usando os registros SSE de 128 bits.

E o padrão CLI diz que os duplos podem ser representados com maior precisão se o hardware suportar:

[Justificativa: esse design permite que a CLI escolha uma representação de alto desempenho específica da plataforma para números de ponto flutuante até que eles sejam colocados em locais de armazenamento. Por exemplo, ele pode deixar variáveis de ponto flutuante nos registros de hardware que fornecem mais precisão do que o usuário solicitou. Na Partição I 69 ao mesmo tempo, os geradores de CIL podem forçar as operações a respeitar regras específicas de idioma para representações através do uso de instruções de conversão. lógica final]

http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf (12.1.3 Manipulando tipos de dados de ponto flutuante)

Acho que é isso que está acontecendo aqui, porque os resultados diferem após os 15 dígitos padrão de precisão de Double. O resultado Math.Exp de 64 bits é mais preciso (possui um dígito extra) porque o .NET de 64 bits internamente está usando um registro FPU com mais precisão do que o registro FPU usado pelo .NET de 32 bits.

questionAnswers(2)

yourAnswerToTheQuestion