NSPredicate 不适用于双值 (%f)?

Posted

技术标签:

【中文标题】NSPredicate 不适用于双值 (%f)?【英文标题】:NSPredicate dont work with double values (%f)? 【发布时间】:2010-01-08 09:42:14 【问题描述】:

我的托管对象有 2 个双字段:“纬度”、“经度”。 我需要获取所有具有特定坐标的对象

此代码不起作用,fetchedObjects count = 0

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"latitude == %f AND longitude == %f", coordinate.latitude, coordinate.longitude];

但是这段代码工作正常,fetchedObjects count = 3:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"latitude == 53.012667 AND longitude == 36.113000"];

【问题讨论】:

【参考方案1】:

它适用于长浮点数,%lf

【讨论】:

正如 jdeprez 所说,您不应该比较浮点值。比较浮点值是危险且不好的做法。相反,使用一个相当大的区域作为谓词,然后从返回的对象数组中计算最接近您正在搜索的点的距离。【参考方案2】:

永远不要使用== 来比较浮点值。

如果要查找具有“特定”值的对象,请与小范围进行比较。否则,浮点表示错误会咬你。

所以考虑使用:

const float epsilon = 0.000001;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"latitude > %f AND latitude < %f AND longitude > %f AND longitude < %f", coordinate.latitude - epsilon,  coordinate.latitude + epsilon, coordinate.longitude - epsilon, coordinate.longitude + epsilon];

【讨论】:

Clang 的 float.h 定义了许多与浮点数和双精度数相关的常量。其中两个是 FLT_EPSILON (1E-5) 和 DBL_EPSILON (1E-9),应该使用它们来代替这里给出的 epsilon 1E-6。这些常量的特征由C99 5.2.4.2.2 定义。 如果您要与双打进行比较,请使用 %lf 现在 Double.ulpOfOne 而不是 DBL_EPSILON(后者已被弃用)。【参考方案3】:

这是因为浮点数的精度不是 100%。所以你也可以这样做:

[NSPredicate predicateWithFormat:@"abs(latitude - %f) < 0.0001 AND abs(longitude - %f) < 0.0001", coordinate.latitude, coordinate.longitude]

【讨论】:

我收到此错误消息:'Invalid predicate', reason: 'The 'abs:' function is not supported.'【参考方案4】:

使用这个转换为 NSNumber:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"latitude == %@ AND longitude == %@", @(coordinate.latitude), @(coordinate.longitude)];

【讨论】:

以上是关于NSPredicate 不适用于双值 (%f)?的主要内容,如果未能解决你的问题,请参考以下文章

NSPredicate 不适用于核心数据中的抽象实体属性

NSFetchRequest 不适用于谓词

具有多个条件的 NSPredicate

python PyQt - 用于浮点或双值+测试的QSlider

python PyQt - 用于浮点或双值+测试的QSlider

NSPredicate 用于评估字符串