Это должно быть легко, но как можно суммировать два NSNumber
? Как:
[one floatValue] + [two floatValue]
или есть лучший способ?
Ответы:
На самом деле нет лучшего способа, но вам действительно не следует этого делать, если вы можете этого избежать. NSNumber
существует как оболочка для скалярных чисел, поэтому вы можете хранить их в коллекциях и передавать их полиморфно с другими NSObjects
. На самом деле они не используются для хранения чисел в реальной математике. Если вы выполняете математические операции с ними, это будет намного медленнее, чем выполнение операции только со скалярами, поэтому, вероятно, для этого не существует удобных методов.
Например:
NSNumber *sum = [NSNumber numberWithFloat:([one floatValue] + [two floatValue])];
Выполняет как минимум 21 инструкцию по отправке сообщений, и сколько бы кода ни занимали методы, чтобы распаковать и переупаковывать значения (вероятно, несколько сотен) для выполнения математических расчетов на одну инструкцию.
Поэтому, если вам нужно хранить числа в dicts, используйте NSNumber
, если вам нужно передать что-то, что может быть числом или строкой, в функцию, используйте NSNumber
, но если вы просто хотите выполнять математические вычисления со скалярными типами C.
NSDecimalNumber (подкласс NSNumber ) имеет все полезности, которые вы ищете:
– decimalNumberByAdding:
– decimalNumberBySubtracting:
– decimalNumberByMultiplyingBy:
– decimalNumberByDividingBy:
– decimalNumberByRaisingToPower:
...
Если интересует производительность вычислений, преобразуйте его в массив C ++ std :: vector или что-то подобное.
Теперь я больше не использую C-Arrays; слишком легко выйти из строя, используя неправильный индекс или указатель. И очень утомительно связывать каждый новый [] с delete [].
NSDecimalNumber
s, как преобразовать NSDecimalNumber
результат обратно в NSNumber
? (Этот вопрос касается сложения двух NSNumber
, а не двух NSDecimalNumber
.)
@interface NSDecimalNumber : NSNumber
Вы можете использовать
NSNumber *sum = @([first integerValue] + [second integerValue]);
Изменить: по наблюдениям ohho , этот пример предназначен для добавления двух NSNumber
экземпляров, которые содержат целые значения. Если вы хотите сложить два NSNumber
, которые содержат значения с плавающей запятой, вы должны сделать следующее:
NSNumber *sum = @([first floatValue] + [second floatValue]);
int
и long
или это большой брат typedef
« под ред NSInteger
в NSNumber
объекты .
integerValue
усекает float
. Как можно проголосовать за этот ответ?
integerValue
если вы хотите сохранить десятичную часть чисел?
Текущий ответ, получивший наибольшее количество голосов, приведет к трудно диагностируемым ошибкам и потере точности из-за использования поплавков. Если вы выполняете числовые операции со значениями 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)
Почему бы не использовать 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]);
}
В Swift вы можете получить эту функциональность с помощью библиотеки Bolt_Swift https://github.com/williamFalcon/Bolt_Swift .
Пример:
var num1 = NSNumber(integer: 20)
var num2 = NSNumber(integer: 25)
print(num1+num2) //prints 45