单精度或双精度小数比较时的误差处理

DBL_EPSILON和 FLT_EPSILON主要用于单精度和双精度的比较当中

我们在对小数比较的时候,经常会出现如下情况:

double a = 0.5;
if (a == 0.5) //正确
    x++;

double b = sin(M_PI / 6.0);
if (b == 0.5) //错误
    x++;

第一个比较正确,第二个可能正确也可能错误,b==0.5的结果取决于处理器、编译器的版本和设置。比如 Visual C++ 2010 编译器编译后运行b的值为0.49999999999999994

这种情况我们就需要用到DBL_EPSILON,具体用法如下:

double b = sin(M_PI / 6.0);
if (fabs(b - 0.5) < DBL_EPSILON)
    x++;

以上的例子可以看出, EPSILON是最小误差。 是EPSILON+X不等于X的最小的正数。

具体的应用我们在FLAnimatedImage中有使用,如下:

if ([delayTime floatValue] < ((float)kFLAnimatedImageDelayTimeIntervalMinimum - FLT_EPSILON)) {
                            FLLog(FLLogLevelInfo, @"Rounding frame %zu's `delayTime` from %f up to default %f (minimum supported: %f).", i, [delayTime floatValue], kDelayTimeIntervalDefault, kFLAnimatedImageDelayTimeIntervalMinimum);
                            delayTime = @(kDelayTimeIntervalDefault);
                        }

delayTime是一个GIF图片一帧的动画时长,floatValue后可能会转换成0.01999999

kFLAnimatedImageDelayTimeIntervalMinimum:等于0.02

实际上我们对这两个数比较的时候,可以认为它们是相等的,但是如果直接比较的话,计算机会认为它们不等。

于是我们通过让kFLAnimatedImageDelayTimeIntervalMinimum-FLT_EPSILON,最终得到:0.01999999这样的数,这样在比较的时候,计算机就会认为它们相等了。

DBL_EPSILON:对应的是double类型的最小误差值。

FLT_EPSILON:对应的是float类型的最小误差值。

 

posted @ 2020-03-25 16:07  zbblogs  阅读(940)  评论(0编辑  收藏  举报