3

由于比较浮动是一个如此困难和有争议的问题,我很惊讶地看到 CGPointEqualToPoint 和其他 CG 比较方法只是这样做:

CG_INLINE bool
__CGPointEqualToPoint(CGPoint point1, CGPoint point2)
{
  return point1.x == point2.x && point1.y == point2.y;
}

在某些情况下这不会导致问题吗?或者,Objective-C 是否与 fabs、epsilon 等进行内置浮点比较?我想知道为什么开发人员在这里选择使用直接相等测试。

4

1 回答 1

8

比较浮点数的问题不在比较中。它在数字中。

每个操作,无论是比较、乘法还是余弦,都必须独立操作:它有一些输入,它产生一些输出。它无法“知道”输入必须调整一定量,除非您提供该量作为另一个输入。

当您比较浮点数或对它们执行任何操作时,请考虑如果这些数字是先前计算的结果并引入了舍入误差会发生什么。您打算计算一些数学值xy,但您有一些近似值xy

现在考虑这个问题:如果你想计算x + y,但你不知道xy因为你只有数字xy,它们可能不同,你怎么能找到x + y?你不能; 是不可能的。当然,如果您知道x并且y大约是xy ,您通常可以进行近似。

现在将其应用于比较。如果您想确定x是否等于y,但您不知道xy,因为您只有数字xy,它们可能不同,您如何确定x是否等于y?你不能; 是不可能的。

但是,在比较的情况下,您无法做出近似值。这是因为比较的导数实际上是无限的:微小的变化会导致值的完全变化(从假到真,反之亦然)。

这只能通过专门设计每个应用程序来解决,以便以自己的方式避免或处理问题。对于某些应用程序,当它们的近似值彼此接近时,接受两个相等的数字是可以的。对于其他应用程序,这将破坏应用程序。在某些情况下,可以允许数字不同的量可能与数字之一成比例。在其他情况下,它可能与某个输入值或计算的其他中间值成比例。或者绝对公差可能是合适的。或者可能非常难以计算允许数字不同的数量。

没有通用的解决方案,因此没有用于“近似”比较浮点运算的通用例程。相反,基本操作被提供给应用程序:相等的比较,确切地说,是相等的比较。超越这一点是您必须专门为您的应用程序设计的东西。

考虑计算sqrt(x)acos(y)如果当真正的数学x不是负数时浮点错误x小于零,或者当真正的数学y小于 1 时浮点错误大于 1,会发生什么?在这些情况下,并生成 NaN 或陷阱。您是否希望数学库将它们替换为在这些情况下提供捏造答案的“近似”平方根或反余弦函数?那是行不通的。在调用函数之前必须认识到问题存在,并且必须由应用程序设计者处理。ysqrtacos

于 2013-06-14T15:30:14.627 回答