【问题标题】:NSPredicate dont work with double values (%f)?NSPredicate 不适用于双值 (%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"];

【问题讨论】:

    标签: iphone core-data


    【解决方案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)];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-05
      • 2023-03-18
      • 2014-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多