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

Есть ли способ создать NSDecimal без использования NSNumber и создания объектов с автореализацией?

Я выполняю ряд вычислений с использованием NSDecimal и создаю каждую структуру NSDecimal, используя следующую технику:

[[NSNumber numberWithFloat:kFloatConstant] decimalValue]

Я использую NSDecimal, чтобы избежать использования объектов с автореализацией NSDecimalNumber (если используется метод NSDecimalNumber для точных вычислений). Однако кажется, что механизм создания NSNumber также возвращает autoreleased NSNumber, из которого извлекается десятичное значение.

Есть ли способ создать NSDecimal без использования NSNumber и создания объектов с автореализацией?

4b9b3361

Ответ 1

К сожалению, Apple не предоставляет каких-либо простых способов размещения значений в структуре NSDecimal. Само определение структуры можно найти в заголовке NSDecimal.h:

typedef struct {
    signed   int _exponent:8;
    unsigned int _length:4;     // length == 0 && isNegative -> NaN
    unsigned int _isNegative:1;
    unsigned int _isCompact:1;
    unsigned int _reserved:18;
    unsigned short _mantissa[NSDecimalMaxSize];
} NSDecimal;

но я не знаю, что я бы попытался перепрограммировать, как структуры хранят значения. Символы подчеркивания полей в структуре указывают, что они являются частными и могут быть изменены. Я не думаю, что в низкоуровневых функциях NSDecimal происходят большие изменения, но в какой-то момент я бы нервничал из-за того, что произошло.

Учитывая, что инициализация NSDecimal из числа с плавающей запятой лучше всего делать так, как вы описываете. Однако имейте в виду, что в любое время, когда вы используете значение с плавающей запятой, вы теряете точность, которую вы приобрели, используя NSDecimal, и будете подвергать себя ошибкам с плавающей запятой.

Я всегда работаю только с NSDecimals в своих высокоточных вычислениях, а также беру и экспортирую NSStrings для обмена этими значениями с внешним миром. Чтобы создать NSDecimal на основе NSString, вы можете использовать подход, который мы применяем в Framework Core Plot:

NSDecimal CPDecimalFromString(NSString *stringRepresentation)
{
    NSDecimal result;
    NSScanner *theScanner = [[NSScanner alloc] initWithString:stringRepresentation];
    [theScanner scanDecimal:&result];
    [theScanner release];

    return result;
}

Использование NSScanner вместо NSDecimalNumber -initWithString:locale: примерно на 90% быстрее в моих тестах.

Ответ 2

Чтобы ответить на часть "без автореализованных объектов", просто:

NSDecimalNumber *intermediateNumber = [[NSDecimalNumber alloc] initWithFloat:kFloatConstant];
NSDecimal decimal = [intermediateNumber decimalValue];
[intermediateNumber release];