2010-01-08 2 views
14

Мой управляемый объект имеет 2 двойных поля: «широта», «долгота». Мне нужно извлечь все объекты, которые имеют определенные координатыNSPredicate не работает с двойными значениями (% f)?

Этот код не работает, граф fetchedObjects = 0

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

Но этот код отлично работает, граф fetchedObjects = 3:

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

ответ

25

он отлично работает с длинным поплавком,% lf

+0

Подтвердите свой ответ, как правильно, если он решит вашу проблему – Vladimir

+3

Как jdeprez заявил, вы не должны быть сравнения значений с плавающей точкой. Сравнение значений float является опасной и плохой практикой. Вместо этого используйте значительную область в качестве предиката, а затем вычислите расстояние от точки, ближайшей к тому, что вы ищете, из массива возвращаемых объектов. – Christopher

+0

Вы сохранили мой день ..... :-) –

14

Oh geez ...

Не используйте == для сравнения значений с плавающей запятой.

Если вы хотите найти объекты со специфическим значением, сравните их с небольшим диапазоном. В противном случае ошибка представления с плавающей запятой укусит вас.

Так рассмотреть вопрос об использовании:

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]; 
+1

Clang's ** float.h ** определяет ряд констант, относящихся к поплавкам и удвоениям. Два из них: «FLT_EPSILON» (1E-5) и «DBL_EPSILON» (1E-9), которые следует использовать вместо приведенного здесь epsilon 1E-6. Характеристики этих констант определены в [C99 5.2.4.2.2] (http://c0x.coding-guidelines.com/5.2.4.2.2.html). –

+1

Используйте '% lf', если вы сравниваете число пар – ken

2

Это потому, что точность поплавков не 100%. Таким образом, вы также можете сделать это:

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

Я получаю это сообщение об ошибке:' '' 'Недопустимый предикат', причина: 'Функция' abs: 'не поддерживается. '' '' –

0

Преобразовать в NSNumber с помощью этого:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"latitude == %@ AND longitude == %@", @(coordinate.latitude), @(coordinate.longitude)]; 
Смежные вопросы