正在使用std::max来比较两个替身是否安全

Is using std::max for comparing two doubles safe?

本文关键字:两个 安全 是否 替身 比较 std max      更新时间:2023-10-16

我知道要比较两个双打,我们必须做这样的

bool AreSame(double a, double b)
{
    return fabs(a - b) < EPSILON;
}

但我不知道std::max是否以相同的方式比较两倍?如果我打电话给你,那就是答案CCD_ 1。我得到了正确的结果,但我仍然不确定!Morover我昨晚在codeforces使用了它,并接受了我的解决方案!

我为什么担心?我查过了http://www.cplusplus.com/有没有写过max的行为与下面的代码相同

template <class T> const T& max (const T& a, const T& b) {
  return (a<b)?b:a;     // or: return comp(a,b)?b:a; for version (2)
}

页面链接

(相对差异为10^-6)

(正如您刚才对问题所做的修改)max应该做一个简单的'<',像

(a < b) ? b : a

这应该是"安全的",因为你可以在两个双打/浮动之间进行比较。然而,doubles/float实际上只是值的近似值,它们可能是也可能不是确切的值。你可以在10进制中看到,它的值是1/3=.3333……写入的十进制值永远不可能是精确的1/3,因为它是一个无限重复的值。为了使处理器使用离散值,必须使用有限数量的位,因此将进行舍入。这使得"相等"的概念有点模糊,实际上你是说两个值近似相等,在给定一定容差(ε)的情况下足够接近。你可以争辩说>和<也受到这种近似过程的变幻莫测的影响。然而,通常人们愿意接受两种价值观具有<或>关系。

事实上,这可能是一个相当复杂的问题。这在很大程度上取决于你在做什么,以及你的应用程序对这些数值近似问题的容忍度。我知道有一个案例,AI算法受到从使用FPU指令到使用MMX/SSE/AVX的变化的影响。。。类型指令(PC FPU通常以80位进行内部计算,然后进行舍入,而AVX指令使用64位从干到尾)。在许多迭代过程中,基于舍入的差异导致采取不同的路径,从而导致不同的结果。这在很大程度上与这些类型的比较有关。你不能说这种方法(取决于FPU的行为)是不正确的,只能说它不能容忍对"较低分辨率"FP计算的更改。

std::max不关心相等,它只关心两个数字不相等的情况。此外,ε与寻找由浮点误差引起的差的近似相等的数字有关。浮点误差应该导致std::max选择一个而不是另一个,因为std::max无法知道什么ε是合适的。

请记住,您的系统可能需要AreSame(0.1000001, 0.1) == true,但std::max(0.1000001, 0.1)应返回0.1000001,以备不时之需。