起初我以为我只能依靠最大相对差,但我错了。例如,a = 0.0
和b = 0.5
,它们的相对差为1.0
。在这种情况下,approxEquals(lhs, rhs, maxRelDiff, maxAbsDiff)
依赖于最大绝对差来确定两个浮点数是否相等。
这两个问题是:
-
如果默认值(1e-2, 1e-5)不够精确,我如何想出一个新的最大相对和绝对差对?如何选择
1e-2
和1e-5
作为默认值?例如,如果我选择1e-4
作为最大相对差,那么最大绝对差是多少? -
如何调整最大相对和绝对差值,使
floats
和doubles
正常工作?
检查源代码给了我这个(我删除了范围的实现)
bool approxEqual(T, U, V)(T lhs, U rhs, V maxRelDiff, V maxAbsDiff = 1e-5)
{
if (rhs == 0)
{
return fabs(lhs) <= maxAbsDiff;
}
static if (is(typeof(lhs.infinity)) && is(typeof(rhs.infinity)))
{
if (lhs == lhs.infinity && rhs == rhs.infinity ||
lhs == -lhs.infinity && rhs == -rhs.infinity) return true;
}
return fabs((lhs - rhs) / rhs) <= maxRelDiff
|| maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff;
}
最后一行是我们需要学习的:
return fabs((lhs - rhs) / rhs) <= maxRelDiff
|| maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff;
换句话说,如果数字相对相差不超过maxRelDiff
的一个因数,或者绝对相差不超过maxAbsDiff
所以使用0.01
(或1E-2
)的maxRelDiff
与2位(十进制)数字的精度比较
和使用不同于0的maxAbsDiff
允许接近于0的数字被认为是相等的,即使相对差异大于maxRelDiff
edit:基本上首先决定比较需要有多准确,并在此基础上选择maxRelDiff
,然后决定在什么时候一个数字应该等于0
和注释中的示例:
approxEqual(1+1e-10, 1.0, 1e-10, 1e-30)
approxEqual(1+1e-10, 1.0, 1e-9, 1e-30)
比较接近1的值,所以maxRelDiff
在这里占上风,选择任何maxAbsDiff
(低于maxRelDiff
)不会改变任何东西
approxEqual(0, 1e-10, 1e-10, 1e-30)
approxEqual(0, 1e-9, 1e-9, 1e-30)
将接近0的值与0进行比较,因此RelDiff (fabs((lhs - rhs) / rhs)
)将为1,maxAbsDiff
将优于
虽然我不能回答你原来的问题,但我个人只是使用fabs
进行浮点比较:
return fabs(f1 - f2) < 0.10;