比较浮点数值有多危险?

420

我知道UIKit使用CGFloat是因为它具有分辨率无关的坐标系统。

但每次我想检查例如frame.origin.x是否为0时,这让我感到不舒服:

if (theView.frame.origin.x == 0) {
    // do important operation
}

CGFloat在使用==<=>=<>进行比较时,是否容易出现误判呢?毕竟它是浮点数,存在精度问题,例如:0.0000000000041

在比较过程中,Objective-C是否会内部处理这个问题呢?或者说可能会出现origin.x读取为零但与0进行比较结果不为真的情况吗?


1
这主要是针对非整数值的问题,其中舍入误差很容易发生。我写了一篇博客文章,描述了何时会发生舍入误差以及如何估计潜在误差的大小。 - Hampus
12个回答

-1
-(BOOL)isFloatEqual:(CGFloat)firstValue secondValue:(CGFloat)secondValue{

BOOL isEqual = NO;

NSNumber *firstValueNumber = [NSNumber numberWithDouble:firstValue];
NSNumber *secondValueNumber = [NSNumber numberWithDouble:secondValue];

isEqual = [firstValueNumber isEqualToNumber:secondValueNumber];

return isEqual;

}


-7

我认为正确的做法是将每个数字声明为一个对象,然后在该对象中定义三个内容:1)相等运算符。2)setAcceptableDifference方法。3)数值本身。如果两个值的绝对差小于设置的可接受值,则相等运算符返回true。

您可以子类化对象以适应问题。例如,在1英寸和2英寸之间的圆形金属棒如果直径相差不到0.0001英寸,则可能被视为具有相等的直径。因此,您可以使用参数0.0001调用setAcceptableDifference,然后放心地使用相等运算符。


2
这不是一个好的答案。首先,“对象”的整个概念根本无助于解决您的问题。其次,您实际上对“相等性”的实现并不正确。 - Tom Swirly
3
汤姆,也许你应该再考虑一下那个“物件的事情”。使用高精度表示的实数,相等很少发生。但如果符合你的要求,你对等式的概念可以进行调整。如果有可覆盖的“约等于”运算符将更好,但现在并没有。 - John White

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接