什么是一个好的经验法则浮点比较方法选择器



我正在测试一些代码,这个数字涉及使用浮点值进行计算,通常是非常大的数字。我有一些通用的(C++模板化的,但为了这个问题,这并不重要)代码,它将我的输出(无论是标量还是数组)与它们的期望值进行比较。

我面临着选择精度阈值的问题,至少对于我正在测试的各种函数的两种C/C++浮点类型floatdouble-来说是这样。众所周知,在比较浮点值方面,没有一个一刀切的方法,也没有一个单独的精度值可以完全根据数据类型进行拟合和计算:相对误差与绝对误差,许多可能会放大浮点舍入误差的运算,本应达到0的计算,因此无法真正通过期望值进行归一化,等等。

选择浮点值的比较方法(和相等阈值)的一般合理方法/算法/经验法则是什么?

我喜欢谷歌测试中使用的方法,例如EXPECT_DOUBLE_EQ(a,b)和EXPECT_FLOAT_EQ(a,b):如果它们在最后一个位置(4 ULP)的4个单位内,则数字大致相等。要做到这一点,你的

  1. 将带符号幅值转换为偏移
  2. 把它们当作整数来减法
  3. 检查差异<=4

这会自动缩放大小并松弛到接近零的绝对值。

没有普遍合理的方法:-(

数字的一个重要性质是,数字集可以划分为等价类,其中同一等价类的所有成员在某种意义上是"相等的",而两个不同等价类的全部成员是"不相等的"。该属性对于排序算法和哈希来说至关重要。

如果你用53位尾数取double,然后用零替换尾数的最后一位,那么你仍然有等价类,排序/哈希也可以。另一方面,用这种方法,两个数字可以任意接近,并且仍然比较相等。

另一种方法是使用一种算法来判断两个数字是否"可能相等"。你可以把其他一切都建立在这个基础上。例如,如果a>b,a"肯定大于"b,并且a不"可能等于"b

排序有问题。你可以有一个"可能等于"b,b"可能相等"c,但a不"可能等同"c。

如果使用53位尾数的double,那么即使在45位内,两个不相关的数字也不太可能相等。因此,你可以非常合理地检查差值的绝对值是否小于较大数字的绝对值,除以2^45。您的里程数会有很大差异。重要的是你是否认为0应该等于非常小的数字。

最新更新