Каков правильный выбор между NSDecimal, NSDecimalNumber, CFNumber?

Не самое быстрое, но это работает!

    static bool IsPrime(long num)
    {
        long checkUpTo = (long)Math.Ceiling(Math.Sqrt(num));
        for (long i = 2; i <= checkUpTo; i++)
        {
            if (num % i == 0)
                return false;
        }
        return true;
    }
28
задан charlax 9 November 2009 в 22:50
поделиться

3 ответа

Если вы имеете дело с финансовыми вычислениями, вам действительно следует использовать арифметику с основанием 10, чтобы избежать ошибок округления, которые могут возникнуть при использовании стандартных типов с плавающей запятой с основанием 2. Так что это либо NSDecimal, либо NSDecimalNumber. А поскольку вы пишете объектно-ориентированный код, NSDecimalNumber - правильный выбор для вас.

Чтобы ответить на ваши вопросы: только тестирование вашего кода может показать, приемлемы ли для вас накладные расходы памяти и потеря производительности. Я не особо много работал с NSDecimalNumber, но держу пари, что реализация Apple достаточно эффективна и будет более чем адекватна потребностям большинства людей.

К сожалению, вы не сможете избежать подобных decimalNumberByAdding: , поскольку Objective-C не поддерживает перегрузку операторов, как это делает C ++. Я согласен с тем, что это делает ваш код несколько менее элегантным.

Один комментарий к опубликованному вами коду: r = [obj performSelector: NSSelectorFromString (@ "capitalizedAmount")]; довольно неэлегантен.

r = [obj performSelector:@selector(capitalizedAmount)];

или даже простой

r = [obj capitalizedAmount];

будет лучше, если вам не требуется синтаксис NSSelectorFromString по какой-либо другой причине.

26
ответ дан 28 November 2019 в 03:18
поделиться

I want to access these methods and setters with their names as strings, since I plan to have a lot of other classes like this one, and I am only keeping a list of field to do key value coding.

r = [obj performSelector:NSSelectorFromString(@"capitalizedAmount")];

KVC - это не просто отправка сообщений объектам с использованием строк. См. Руководство по программированию кодирования значений ключа .

Должен ли я получать значения с плавающей запятой из NSDecimalNumber, а затем выполнять вычисления и возвращать результат, заключенный в NSDecimalNumber?

Нет. Преобразование в двоичное число с плавающей запятой ( float / double ) из десятичного числа с плавающей запятой ( NSDecimal / NSDecimalNumber) выполняется с потерями. Если вы сделаете это так, ваш результат будет неверным для некоторых вычислений.

3
ответ дан 28 November 2019 в 03:18
поделиться

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

В качестве примера я протестировал математические операции для двух типов на моем MacBook Air:

NSDecimal

Additions per second: 3355476.75
Subtractions per second: 3866671.27
Multiplications per second: 3458770.51
Divisions per second: 276242.32

NSDecimalNumber

Additions per second: 676901.32
Subtractions per second: 671474.6
Multiplications per second: 720310.63
Divisions per second: 190249.33

Деления были единственная операция, производительность которой не увеличилась примерно в пять раз при использовании NSDecimal по сравнению с NSDecimalNumber. Подобные улучшения производительности происходят и на iPhone. Это, наряду с экономией памяти, было причиной, по которой мы недавно переключили Core Plot на использование NSDecimal.

Единственная трудность для вас ' Я столкнусь с получением значений в типы NSDecimal и из них. Переход напрямую к значениям с плавающей запятой и целочисленным значениям и обратно может потребовать использования NSDecimalNumber в качестве моста. Кроме того, если вы используете Core Data, вы будете хранить свои значения как NSDecimalNumbers, а не NSDecimals.

19
ответ дан 28 November 2019 в 03:18
поделиться