Подтвердить что ты не робот

Как использовать NSDecimalNumber?

Я создаю приложение, которое должно выполнять вычисления на деньги.

Интересно, как правильно использовать NSDecimalNumber, особенно, как инициализировать его из целых чисел, поплавков и удвоений?

Мне было легко использовать метод -decimalNumberWithString:. Методы -initWith... обескуражены, так что они оставлены только с мантиссой, но никогда ни на одном из 7 языков, которые я использовал раньше, мне это нужно, поэтому я не знаю, что там было...

4b9b3361

Ответ 1

Do НЕ использовать методы NSNumber +numberWith... для создания объектов NSDecimalNumber. Они объявляются как возвращаемые объекты NSNumber и не могут функционировать как экземпляры NSDecimalNumber.

Это объясняется в этой нитке Билла Бумгарнера, разработчика Apple. Я бы посоветовал вам указать ошибку в этом поведении, ссылаясь на ошибку rdar://6487304.

В качестве альтернативы это все подходящие методы для создания NSDecimalNumber:

+ (NSDecimalNumber *)decimalNumberWithMantissa:(unsigned long long)mantissa
                     exponent:(short)exponent isNegative:(BOOL)flag;
+ (NSDecimalNumber *)decimalNumberWithDecimal:(NSDecimal)dcm;
+ (NSDecimalNumber *)decimalNumberWithString:(NSString *)numberValue;
+ (NSDecimalNumber *)decimalNumberWithString:(NSString *)numberValue locale:(id)locale;

+ (NSDecimalNumber *)zero;
+ (NSDecimalNumber *)one;
+ (NSDecimalNumber *)minimumDecimalNumber;
+ (NSDecimalNumber *)maximumDecimalNumber;
+ (NSDecimalNumber *)notANumber;

Если вы просто хотите, чтобы NSDecimalNumber из константы float или int попробовал что-то вроде этого:

NSDecimalNumber *dn = [NSDecimalNumber decimalNumberWithDecimal:
                             [[NSNumber numberWithFloat:2.75f] decimalValue];

Ответ 2

Правильный способ заключается в том, чтобы сделать это:

NSDecimalNumber *floatDecimal = [[[NSDecimalNumber alloc] initWithFloat:42.13f] autorelease];
NSDecimalNumber *doubleDecimal = [[[NSDecimalNumber alloc] initWithDouble:53.1234] autorelease];
NSDecimalNumber *intDecimal = [[[NSDecimalNumber alloc] initWithInt:53] autorelease];

NSLog(@"floatDecimal floatValue=%6.3f", [floatDecimal floatValue]);
NSLog(@"doubleDecimal doubleValue=%6.3f", [doubleDecimal doubleValue]); 
NSLog(@"intDecimal intValue=%d", [intDecimal intValue]);

Подробнее здесь.

Ответ 3

Подумайте, вы должны стараться избегать преобразования NSDecimalNumber или NSDecimals в и из значений int, float и double по тем же причинам, по которым рекомендуется использовать NSDecimalNumbers: потеря точности и двоичные проблемы с плавающей запятой. Я знаю, иногда это неизбежно (принимая входные данные с ползунка, делая тригонометрические вычисления и т.д.), Но вы должны попытаться взять данные от пользователей как NSStrings, а затем использовать initWithString: locale: или decimalNumberWithString: locale: для генерации NSDecimalNumbers. Выполняйте всю свою математику с помощью NSDecimalNumbers и возвращайте свое представление пользователям или сохраняйте их в SQLite (или везде) как их строковое описание, используя descriptionWithLocale:.

Если вам нужно вводить данные из int, float или double, вы можете сделать что-то вроде следующего:

int myInt = 3;
NSDecimalNumber *newDecimal = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%d", myInt]];

или вы могли бы следить за предложением Эшли, чтобы убедиться, что вы в безопасности в десятичной конструкции.