c# - 为什么 Math.Exp 在 32 位和 64 位之间给出不同的结果,具有相同的输入,相同的硬件

标签 c# .net math 32bit-64bit x86-64

我将 .NET 2.0 与 PlatformTarget x64 和 x86 一起使用。我给 Math.Exp 相同的输入数字,它在任一平台上返回不同的结果。

MSDN 说你不能依赖文字/解析的 Double 在平台之间表示相同的数字,但我认为我在下面使用 Int64BitsToDouble 避免了这个问题并保证在两个平台上对 Math.Exp 的输入相同。

我的问题是为什么结果不同?我本以为:

  • 输入以相同的方式存储( double /64 位精度)
  • 无论处理器的位数如何,FPU 都会执行相同的计算
  • 输出以同样的方式存储

我知道一般情况下我不应该比较第 15/17 位之后的 float ,但我对这里的不一致与在同一硬件上看似相同的操作感到困惑。

有人知道幕后发生了什么吗?

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

打开或关闭 JIT 的两个平台上的结果是一致的。

[编辑]

我对下面的答案并不完全满意,所以这里是我搜索的更多详细信息。

http://www.manicai.net/comp/debugging/fpudiff/说:

So 32-bit is using the 80-bit FPU registers, 64-bit is using the 128-bit SSE registers.

而且 CLI 标准说,如果硬件支持, double 可以用更高的精度表示:

[Rationale: This design allows the CLI to choose a platform-specific high-performance representation for floating-point numbers until they are placed in storage locations. For example, it might be able to leave floating-point variables in hardware registers that provide more precision than a user has requested. At the Partition I 69 same time, CIL generators can force operations to respect language-specific rules for representations through the use of conversion instructions. end rationale]

http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf (12.1.3 float 据类型的处理)

我认为这就是这里发生的情况,因为在 Double 的标准 15 位精度之后结果不同。 64 位 Math.Exp 结果更精确(它有一个额外的数字),因为在内部 64 位 .NET 使用的 FPU 寄存器比 32 位 .NET 使用的 FPU 寄存器更精确。

最佳答案

是的舍入错误,它实际上不是同一个硬件。 32 位版本针对一组不同的指令和寄存器大小。

关于c# - 为什么 Math.Exp 在 32 位和 64 位之间给出不同的结果,具有相同的输入,相同的硬件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4018895/

相关文章:

c# - 流式数据 BlockingCollection

c# - 使 session 过期

javascript - 在 Javascript 中计算 RGB 色 block 平均值的更有效方法

java - 圆周率误差

c# - 将 CSS 类添加到代码隐藏的客户端超链接

c# - 无法将类型字符串隐式转换为 int

c# - 如何检测 .Net 中的装箱原因?

c# - 请求被中止无法创建 SSL/TLS 安全通道 webClient C#

.net - 如何仅序列化某些对象属性

Java:多次设置int值