如何比较双数?

yak*_*yak 1 c floating-point double comparison double-precision

我知道当我想检查双倍==双时我应该写:

bool AreSame(double a, double b)
{
    return fabs(a - b) < EPSILON;
}
Run Code Online (Sandbox Code Playgroud)

但是当我想检查是否a > bb > a

Eri*_*hil 6

没有通用的解决方案来比较包含先前操作错误的浮点数.必须使用的代码是特定于应用程序的.因此,要获得正确的答案,您必须更具体地描述您的情况.例如,如果要对列表或其他数据结构中的数字进行排序,则不应使用任何容差进行比较.

通常,如果您的程序需要比较两个数字的顺序但不能这样做,因为它只有这些数字的近似值,那么您应该重新设计程序而不是试图允许数字被错误地排序.

根本问题是使用不正确的数据执行正确的计算通常是不可能的.如果要计算两个精确的数学值的一些功能,XŸ,但你拥有的唯一数据是不正确的一些计算值xy,这是一般不可能计算完全正确的结果.例如,假设你想知道和,x + y是什么,但你只知道x是3并且y是4,但你不知道真正的,精确的xy是什么.然后你无法计算x + y.

如果你知道,xy大约 XŸ,那么你可以计算的近似X通过增加+ Y xy.当计算函数具有合理的导数时,工作:稍微改变具有合理导数的函数的输入会略微改变其输出.当您要计算的函数具有不连续性或大的导数时,这会失败.例如,如果要使用近似值计算x的平方根(在实域中),xx由于先前的舍入误差可能为负,则计算sqrt(x)可能会产生异常.同样,比较不平等或顺序是一个不连续的函数:输入的微小变化可以完全改变答案.

常见的不好建议是与"容忍度"进行比较.对于误报(错误接受不满足比较的数字),此方法交换假阴性(错误拒绝数字,如果比较真实的数学值,将满足比较).

是否适用可以容忍错误接受取决于申请.因此,没有一般的解决方案.

设定的容差水平,甚至计算的性质,取决于数据,误差和先前的计算.因此,即使可以接受与公差进行比较,使用的公差量以及如何计算公差也取决于应用.没有通用的解决方案.