Метод compare: следует стандартным правилам C для преобразования типов. Например, если вы сравниваете объект NSNumber, имеющий целочисленное значение, с объектом NSNumber, который имеет значение с плавающей запятой, целое значение преобразуется в значение с плавающей запятой для сравнения.
Кроме того, инициализация NSNumber с плавающей точкой, а затем преобразование его в double теряет некоторую точность.
NSNumber* number1 = [NSNumber numberWithFloat:1.004];
NSNumber* number2 = [NSNumber numberWithDouble:1.004];
NSLog(@"number1 double: %1.16f", [number1 doubleValue]);
NSLog(@"number2 double: %1.16f", [number2 doubleValue]);
NSLog(@"number1 objCType %s", [number1 objCType]);
NSLog(@"number2 objCType %s", [number2 objCType]);
2012-02-09 15:59:49.487 testNSNumber[89283:f803] number1 double: 1.0039999485015869
2012-02-09 15:59:49.488 testNSNumber[89283:f803] number2 double: 1.0040000000000000
2012-02-09 16:21:01.655 testNSNumber[4351:f803] number1 objCType f
2012-02-09 16:21:01.656 testNSNumber[4351:f803] number2 objCType d
Если вы знаете, что у вас может быть сочетание чисел с плавающей запятой и парных чисел, одним из решений является сравнение значений NSNumber floatValues, как вы делали это в последней строке фрагмента кода в вашем вопросе.
Кроме того, вы можете получить тип данных в NSNumber с помощью метода objCType.