因为比较浮点数是such a difficult and debated issue我很惊讶地看到CGPointEqualToPoint和其他CG比较方法只是这样做:
CG_INLINE bool
__CGPointEqualToPoint(CGPoint point1, CGPoint point2)
{
return point1.x == point2.x && point1.y == point2.y;
}
在某些情况下,这不会导致问题吗?或者Objective-C是否与fabs,epsilon以及所有这些进行内置的浮点比较?我想知道为什么开发人员选择在这里使用直接相等测试。
答案 0 :(得分:8)
比较浮点数的问题不在比较中。这是数字。
每个操作,无论是比较还是乘法或余弦,都必须独立运行:它有一些输入,它产生一些输出。它不能“知道”输入必须调整一定量,除非您将该数量作为另一个输入提供。
当您比较浮点数时,或者对它们执行任何操作时,请考虑如果数字是先前计算引入舍入错误的结果,会发生什么。您打算计算一些数学值 x 和 y ,但您有一些近似值x
和y
。
现在考虑这个问题:如果你想计算 x + y ,但你不知道 x 或 y < / em>因为你只有数字x
和y
,这些数字可能不同,你怎么能找到 x + y ?你不能;是不可能的。当然,如果您知道x
和y
大约是 x 和 y ,您通常可以进行近似。
现在将此应用于比较。如果您想确定 x 是否等于 y ,但您不知道 x 或 y ,因为您只有数字x
和y
可能不同,您如何找到 x 是否等于 y ?你不能;这是不可能的。
但是,在比较的情况下,您无法进行近似。这是因为比较的导数实际上是无限的:微小的变化可能导致值的完全变化(从假到真,反之亦然)。
这只能通过专门设计每个应用程序来解决,以避免或以自己的方式处理问题。对于某些应用程序,当它们的近似值彼此接近时接受两个数字相等是可以的。对于其他应用程序,这将破坏应用程序。在某些情况下,允许数字不同的数量可能与其中一个数字成比例。在其他情况下,它可能与某些输入值或计算的其他中间值成比例。或者绝对容差可能是合适的。或者,计算允许数字不同的数量可能非常困难。
没有通用解决方案,因此没有“近似”比较浮点运算的通用例程。相反,基本操作被提供给应用程序:相等的比较恰好是相等的比较。超出这个范围是你必须专门为你的应用程序设计的。
考虑计算sqrt(x)
或acos(y)
。当真正的数学 x 不是负数时,如果浮点错误使x
小于零,或者当真正的数学<{1}}大于1时,会发生什么? em> y 会不到一个?在这些情况下,y
和sqrt
会生成NaN或陷阱。您是否希望数学库用“近似”平方根或反余弦函数替换它们,这些函数在这些情况下提供了捏造的答案?那是行不通的。必须认识到问题存在之前调用函数,并且必须由应用程序设计者处理。