F# - 如何比较浮点数

时间:2013-06-11 09:31:42

标签: f# floating-point floating-accuracy

在F#中。如何有效地比较浮点数几乎相等的平等?它也适用于非常大和非常小的值。我想首先比较Exponent然后比较Significand(尾数),同时忽略其52位的最后4位。这是一个好方法吗?如何获得浮点数的Exponent和Significand?

2 个答案:

答案 0 :(得分:3)

当您询问如何比较几乎相等的浮点值时,您会问:

  • 我有两个值xy,它们是用浮点运算计算的,因此它们包含舍入误差,并且是理想数学值 x 的近似值和 y 。如何使用浮点xy来比较数学 x y 是否相等?

这里有两个问题:

  1. 我们不知道xy可能存在多少错误。算术的某些组合放大了错误,而其他组合则缩小了它们。 xy中的错误可能从零到无穷大,并且您没有向我们提供任何有关此错误的信息。
  2. 通常假设当xy不相等但彼此接近时,目标是产生“相等”的结果。这会将假阴性(即使数学 x y 相等)报告为不等式转换为正数。但是,它会产生误报(即使数学 x y 不相等,也会报告相等)。
  3. 这些问题没有一般解决方案。

    • 不可能一般地知道应用程序在不知道有关该应用程序的具体细节的情况下,是否可以容忍被告知值不相等,反之则相反。
    • 不可能一般地知道xy可能存在多少错误。

    因此,对于已经近似计算的值的相等性,没有正确的通用测试。

    请注意,此问题并非与测试相等性有关。通常,不可能计算不正确数据的任何函数(除了常数函数之类的普通函数)。由于xy包含错误,因此无法使用x计算没有错误的日志( x ),或计算arcosine( y )或sqrt( x )没有错误。实际上,如果错误使y稍微大于1而y没有,或x稍微小于零而 x 不是,那么计算acos(y)sqrt(x)会产生异常和NaN,即使理想的数学值可以毫无问题地工作。

    这一切意味着您不能简单地将精确的数学运算转换为近似浮点运算并期望获得良好的结果(无论您是否正在测试相等性)。您必须考虑将精确算术转换为近似算术的效果,并评估它们如何影响您的程序和数据。浮点运算的使用,包括相等的比较,必须根据具体情况进行调整。

答案 1 :(得分:2)

F#float只是System.Double的简写。在这种情况下,您可以使用BitConverter.DoubleToInt64Bits方法有效地(并且安全!)将“F#float值”投射到int64;这很有用,因为它避免了像约翰在评论中提到的那样分配byte[]。您可以使用一些简单的按位运算从int64获取指数和有效数。

正如约翰所说,你可能最好通过简单检查相对准确性。对于许多用例而言,它可能是最快的解决方案并且“足够接近”(例如,检查迭代求解器是否已融合到解决方案上)。如果您需要特定的准确度,请查看NUnit的代码 - 它有一些很好的API用于声明值在特定百分比或预期值的ulps数量内。