6

我在 C# 3.0 中有一个基于结构的小型 3D 矢量类,它使用 double 作为基本单位。

一个例子:一个向量的 y 值为

-20.0 straight

我减去一个 y 值为

10.094999999999965

我期望的 y 值是

-30.094999999999963         (1)

相反,我得到

-30.094999313354492         (2)

当我在一个线程中进行整个计算时,我得到 (1)。调试器和 VS 快速监视也返回 (1)。但是,当我在一个线程中运行几次迭代然后从另一个线程调用该函数时,结果是 (2)。现在,调试器也返回 (2)!

我们必须记住,.NET JIT 可能会将值写回内存(网站 Jon Skeet),这会将精度从 80 位(FPU)降低到 64 位(双精度)。但是,(2)的准确度远低于此。

矢量类看起来基本上是这样的

public struct Vector3d
{
  private readonly double _x, _y, _z;
  ...
  public static Vector3d operator -(Vector3d v1, Vector3d v2)
  {
      return new Vector3d(v1._x - v2._x, v1._y - v2._y, v1._z - v2._z);
  }  
}

计算就这么简单

Vector3d pos41 = pos4 - pos1;
4

1 回答 1

5

是的,我相信结果可能取决于线程。

我的猜测是您在代码中的某个位置使用 DirectX - 它设置了 FPU 的精度,我相信它是基于每个线程设置的。

要解决此问题,请在调用时使用D3DCREATE_FPU_PRESERVE标志CreateDevice。请注意,这可能会对性能产生影响。托管等效项是CreateFlags.FpuPreserve.

(请参阅这个相关问题。我没有建议将这个问题作为副本关闭,因为它们至少在表面上看起来有点不同。两者都应该有助于发现答案。)

于 2010-05-17T09:40:23.123 回答