相关疑难解决方法(0)

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

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

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

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

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

我知道我不应该比较15/17位数后的浮点数,但我对这里的不一致感到困惑,看起来在同一硬件上看起来是相同的操作.

任何人都知道引擎盖下发生了什么?

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
Run Code Online (Sandbox Code Playgroud)

在打开或关闭JIT的两个平台上,结果都是一致的.

[编辑]

我对下面的答案并不完全满意,所以这里有一些我搜索的细节.

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

因此32位使用80位FPU寄存器,64位使用128位SSE寄存器.

CLI标准表示,如果硬件支持双精度,则可以用更高的精度表示双精度:

[原理:此设计允许CLI为浮点数选择特定于平台的高性能表示,直到它们被放置在存储位置.例如,它可能能够在硬件寄存器中保留浮点变量,这些变量提供的精度比用户请求的更高.在分区I 69同时,CIL生成器可以通过使用转换指令强制操作遵守特定于语言的表示规则.最终理由]

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

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

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

11
推荐指数
1
解决办法
2064
查看次数

为什么相同的代码会在32位与64位计算机上产生不同的数字结果?

我们正在使用C语言中的数字例程库.我们还不确定是否可以使用单精度(float)或double(double),因此我们将类型定义SP为别名,直到我们决定:

typedef float SP;
Run Code Online (Sandbox Code Playgroud)

当我们运行我们的单元测试时,它们都会通过我的机器(一个64位的Ubuntu),但它们在我的同事(一个错误地安装在64位机器上的32位Ubuntu)上失败了.

使用Git的bisect命令,我们发现确切的差异开始在他的机器和我的机器之间产生不同的结果:

-typedef double SP;
+typedef float SP;
Run Code Online (Sandbox Code Playgroud)

换句话说,从双精度到单精度会在我们的机器上产生数值上不同的结果(在最坏情况下约为1e-3相对差异).

我们相当肯定,我们永远不会将无符号的整数与负数签名的整数进行比较.

为什么数字例程库会在32位操作系统和64位系统上产生不同的结果?

澄清

我担心我可能不够清楚:我们有2f3f671使用双精度的Git提交,并且单元测试在两台机器上同样通过.然后我们有git的承诺46f2ba,我们改为单精度,这里的测试仍然通过64位的计算机上,但不能在32位机器上.

c floating-point

6
推荐指数
1
解决办法
1358
查看次数

标签 统计

.net ×1

32bit-64bit ×1

c ×1

c# ×1

floating-point ×1

math ×1

x86-64 ×1