2010-01-08 10 views
14

Mi objeto administrado tiene 2 campos dobles: "latitud", "longitud". necesito para recuperar todos los objetos, que tiene ciertas coordenadasNSPredicate ¿no funciona con valores dobles (% f)?

Este código no funciona, cuentan fetchedObjects = 0

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

Pero este buen trabajo de código, cuentan fetchedObjects = 3:

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

Respuesta

25

funciona bien con flotador largo,% lf

+0

acepta su respuesta como correcta, si resuelve su problema – Vladimir

+3

Como jdeprez indicó que no se debe comparar los valores de coma flotante. Comparar los valores de flotación es una práctica peligrosa y mala. En su lugar, use una región considerable como predicado, luego calcule la distancia desde el punto más cercano a lo que está buscando desde la matriz de objetos devueltos. – Christopher

+0

Has guardado mi día ..... :-) –

14

Oh, vaya ...

No use == para comparar valores de punto flotante, nunca.

Si desea encontrar objetos con un valor "específico", compare con un rango pequeño. De lo contrario, el error de representación de coma flotante te morderá.

Así que considerar el uso de:

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 ** float.h ** define un número de constantes relevantes para los flotantes y los dobles. Dos de ellos son 'FLT_EPSILON' (1E-5) y' DBL_EPSILON' (1E-9), que se deben usar en lugar del épsilon 1E-6 que se da aquí. Las características de estas constantes están definidas por [C99 5.2.4.2.2] (http://c0x.coding-guidelines.com/5.2.4.2.2.html). –

+1

Use '% lf' si compara con Dobles – ken

2

Es porque la precisión de los flotadores no es 100%. Por lo que también podría hacer esto:

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

Aparece el siguiente mensaje de error:' '' Predicador inválido ', razón:' La función 'abs:' no es compatible.'''' –

0

Convertir a NSNumber usando esto:

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