Как добавить два объекта NSNumber? - PullRequest
76 голосов
/ 30 января 2009

Теперь это должно быть легко, но как можно сложить два NSNumber? Это как:

[one floatValue] + [two floatValue]

или существует лучший способ?

Ответы [ 6 ]

140 голосов
/ 30 января 2009

Нет лучшего способа, но вы действительно не должны этого делать, если можете избежать этого. NSNumber существует как оболочка для скалярных чисел, поэтому вы можете хранить их в коллекциях и полиморфно передавать их другим NSObjects. Они не используются для хранения чисел в реальной математике. Если вы выполняете математику с ними, это намного медленнее, чем выполнение операции только со скалярами, поэтому, вероятно, для этого нет удобных методов.

Например:

NSNumber *sum = [NSNumber numberWithFloat:([one floatValue] + [two floatValue])];

Дает не менее 21 инструкции по отправке сообщений, и сколько бы кода не понадобилось методам, чтобы распаковать и перезаписать значения (вероятно, несколько сотен), чтобы выполнить математическую операцию на 1 инструкцию.

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

48 голосов
/ 23 июня 2011

NSDecimalNumber (подкласс NSNumber ) содержит все нужные вам вкусности:

– decimalNumberByAdding:
– decimalNumberBySubtracting:
– decimalNumberByMultiplyingBy:
– decimalNumberByDividingBy:
– decimalNumberByRaisingToPower:

...

Если производительность вычислений представляет интерес, тогда преобразуйте в C ++ массив std :: vector или тому подобное.

Теперь я никогда больше не использую C-массивы; слишком легко потерпеть крах, используя неправильный индекс или указатель. И очень утомительно связывать каждое новое [] с delete [].

11 голосов
/ 14 ноября 2013

Вы можете использовать

NSNumber *sum = @([first integerValue] + [second integerValue]);

Edit: Как замечено ohho , этот пример предназначен для сложения двух экземпляров NSNumber, которые содержат целочисленные значения. Если вы хотите добавить два NSNumber, которые содержат значения с плавающей запятой, вы должны сделать следующее:

NSNumber *sum = @([first floatValue] + [second floatValue]);
4 голосов
/ 17 января 2017

Текущий ответ с наибольшим количеством голосов приведет к трудно диагностируемым ошибкам и потере точности из-за использования поплавков. Если вы выполняете числовые операции над значениями NSNumber, вам следует сначала преобразовать их в NSDecimalNumber и вместо этого выполнять операции с этими объектами.

Из документации :

NSDecimalNumber, неизменяемый подкласс NSNumber, предоставляет объектно-ориентированную оболочку для выполнения арифметики с основанием 10. Экземпляр может представлять любое число, которое может быть выражено как показатель мантиссы x 10 ^, где мантисса - это десятичное целое число длиной до 38 цифр, а показатель степени - это целое число от –128 до 127.

Следовательно, вы должны преобразовать свои экземпляры NSNumber в NSDecimalNumbers с помощью [NSNumber decimalValue], выполнить любую арифметику, какую хотите, а затем назначить обратно NSNumber, когда закончите.

В Objective-C:

NSDecimalNumber *a = [NSDecimalNumber decimalNumberWithDecimal:one.decimalValue]
NSDecimalNumber *b = [NSDecimalNumber decimalNumberWithDecimal:two.decimalValue]
NSNumber *result = [a decimalNumberByAdding:b]

В Swift 3:

let a = NSDecimalNumber(decimal: one.decimalValue)
let b = NSDecimalNumber(decimal: two.decimalValue)
let result: NSNumber = a.adding(b)
0 голосов
/ 20 февраля 2019

Почему бы не использовать NSxEpression?

NSNumber *x = @(4.5), *y = @(-2);

NSExpression *ex = [NSExpression expressionWithFormat:@"(%@ + %@)", x, y];
NSNumber *result = [ex expressionValueWithObject:nil context:nil];

NSLog(@"%@",result); // will print out "2.5"

Вы также можете создать выражение NSE, которое можно использовать повторно для оценки с другими аргументами, например:

NSExpression *expr = [NSExpression expressionWithFormat: @"(X+Y)"];
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:x, @"X", y, @"Y", nil];
NSLog(@"%@", [expr expressionValueWithObject:parameters context:nil]);

Например, мы можем циклически оценивать одно и то же проанализированное выражение, каждый раз с другим значением «Y»:

 for (float f=20; f<30; f+=2.0) {
    NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:x, @"X", @(f), @"Y", nil];
    NSLog(@"%@", [expr expressionValueWithObject:parameters context:nil]);
 }
0 голосов
/ 17 мая 2015

В Swift вы можете получить эту функциональность, используя библиотеку Bolt_Swift https://github.com/williamFalcon/Bolt_Swift.

Пример:

  var num1 = NSNumber(integer: 20)
  var num2 = NSNumber(integer: 25)
  print(num1+num2) //prints 45
...