Ошибка точности с использованием NSNumberFormatter numberFromString

Почему следующий код создает «numberFromString = 9.390000000000001», а не «numberFromString = 9.39»?

NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numFormatter setPositiveFormat:@"$##0.00"];
[numFormatter setNegativeFormat:@"-$##0.00"];
NSNumber *nTCA = [numFormatter numberFromString:@"$9.39"];

NSLog(@"numberFromString = %@", nTCA);

Я получаю указанные выше результаты на OS X 10.6 и iOS 4.3.3.

Как лучше всего исправить эту ошибку?

Спасибо


person Rob Wright    schedule 20.06.2011    source источник


Ответы (1)


Я подозреваю, что вы столкнулись с ошибкой в ​​результате использования точности с плавающей запятой. Чтобы исправить это, используйте NSDecimalNumber вместо NSNumber. Есть отличный пост об этом здесь.

NSDecimalNumber имеет _ 4_. Достаточно ли этого для ваших целей?

person Nate Thorn    schedule 20.06.2011
comment
Единственная проблема с этой статьей заключается в том, что автор забывает, что NSDecimalNumber является подклассом NSNumber и поэтому реагирует на такие вещи, как +numberWithInt: и +numberWithDouble:. Вам не нужно использовать +decimalNumberWithMantissa:exponent:isNegative: для их создания из примитивов. - person JeremyP; 21.06.2011
comment
@JeremyP На самом деле, поскольку +numberWithInt:, +numberWithDouble: и тому подобное возвращают NSNumber*, я почти уверен, что вы не можете использовать их для создания NSDecimalNumber*. См. Этот вопрос SO: stackoverflow.com/questions/453691/how-use-nsdecimalnumber < / а> - person Nate Thorn; 21.06.2011
comment
@Nate Thorn: [NSDecimalNumber numberWithInt: x] даст тебе NSDecimalNumber - person JeremyP; 21.06.2011
comment
@Nate Thorn: И даже если это не так, эквивалентные -initWith... методы определенно должны. - person JeremyP; 21.06.2011
comment
@JeremyP Ну, похоже, дело в API. В API указано, что методы +numberWithInt: возвращают NSNumber* (неспециализированные), поэтому технически нельзя предполагать, что они будут NSDecimalNumber*s. При этом я только что провел быстрый тест, и похоже, что они определенно возвращают NSDecimalNumber*s. В конце концов, я полагаю, это сводится к вопросу философии. Вы слепо следуете API до буквы или вы просто бросаете проклятую вещь и продолжаете жить? :) - person Nate Thorn; 21.06.2011
comment
@Nate Thorn: Я тоже попробовал тот же тест и получил обратно NSDecimalNumber. Однако, поразмыслив, я думаю, что согласился бы с вами и придерживался -initWith... методов просто в целях безопасности. Я только что нашел метод +array NSArray, который можно отправить в NSMutableArray, чтобы получить изменяемый массив, и его возвращаемый тип - id (и он также явно говорит, что он используется подклассами в документации). - person JeremyP; 21.06.2011