C# Misc Utils - 运算符 <T> 通用数学精度问题
C# Misc Utils - Operator<T> Generic Math Precision Issues
我将 Jon Skeet 的 Misc Util 库与 Marc 的运算符泛型数学结合使用 class。我发现了精度问题,如果我正常进行数学计算,我不会发现这些问题。
例如,与常规浮点类型运算符相比,我在计算向量叉积时发现类似 .0001 的错误。
这是意料之中的事吗?
[Test]
public static void Reproduce_OperatorT_Issue()
{
float termFive = Operator<float>.Multiply(5.3f, 56.0f);
float termSix = Operator<float>.Multiply(6.5f, 55.0f);
float newZ = Operator<float>.Subtract(termFive, termSix);
Assert.AreEqual(newZ, 5.3f * 56.0f - 6.5f * 55.0f);
}
输出:预期:-60.6999817f 但实际为:-60.6999893f
这似乎符合浮动类型的规范4.1.6 Floating point types
这是不幸的。如果需要,JIT 似乎可以执行双精度,但我想 JIT 不会对 Operator 中的那些表达式执行相同的操作,这是我对这些精度问题的唯一解释。
编辑:正如其他人在评论中指出的那样,C# 编译器、CLR 和 JIT 都可以自由控制浮点数以及它们对浮点数的处理方式,因此不保证值是等价的。
我将 Jon Skeet 的 Misc Util 库与 Marc 的运算符泛型数学结合使用 class。我发现了精度问题,如果我正常进行数学计算,我不会发现这些问题。
例如,与常规浮点类型运算符相比,我在计算向量叉积时发现类似 .0001 的错误。
这是意料之中的事吗?
[Test]
public static void Reproduce_OperatorT_Issue()
{
float termFive = Operator<float>.Multiply(5.3f, 56.0f);
float termSix = Operator<float>.Multiply(6.5f, 55.0f);
float newZ = Operator<float>.Subtract(termFive, termSix);
Assert.AreEqual(newZ, 5.3f * 56.0f - 6.5f * 55.0f);
}
输出:预期:-60.6999817f 但实际为:-60.6999893f
这似乎符合浮动类型的规范4.1.6 Floating point types 这是不幸的。如果需要,JIT 似乎可以执行双精度,但我想 JIT 不会对 Operator 中的那些表达式执行相同的操作,这是我对这些精度问题的唯一解释。
编辑:正如其他人在评论中指出的那样,C# 编译器、CLR 和 JIT 都可以自由控制浮点数以及它们对浮点数的处理方式,因此不保证值是等价的。