如何添加两个NSNumber对象?


79

现在,这一定很容易,但是如何求和两个NSNumber呢?就好像:

[one floatValue] + [two floatValue]

还是存在更好的方法?

Answers:


143

确实没有更好的方法,但是如果可以避免的话,您实际上不应该这样做。NSNumber作为标量数字的包装器而存在,因此您可以将它们存储在集合中,并与其他变量进行多态传递NSObjects。它们并没有真正用于在实际数学中存储数字。如果对它们进行数学运算,则比仅对标量执行运算要慢得多,这可能就是为什么没有便捷方法的原因。

例如:

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

在消息分发上至少要消耗21条指令,但是该方法需要花费大量代码来对取消装箱并重新装箱值(可能是几百个)来完成1条指令的数学运算。

因此,如果您需要将数字存储在字典中,请使用NSNumber,如果您需要将可能是数字或字符串的内容传递给函数,请使用NSNumber,但是如果您只想对标量C类型进行数学计算。


1
我要补充一点,如果您需要存储打算进行大量数学运算的数字集合-也许您真的想要一个具有适当数字类型的C样式数组?
肯德尔·赫尔姆斯特·盖尔纳

每当进行大量数学运算时,您都想使用标量,当您需要多态性或它们需要适合现有容器时,就想使用对象。
Louis Gerbarg,

NSNumber的正确方法是'numberWithFloat:'-也许自从回答以来,这种情况就已经改变了。
尼克,2010年

没错,getter是floatValue,所以我习惯在两个地方都键入它,但是stackoverflow不会给我编译错误。已修正
Louis Gerbarg

2
@clopez:“医生,当我这样做时会很痛。” NSNumber是用于容器的盒装类型,而不用于算术。如果要进行算术运算,请使用算术类型。
斯蒂芬·佳能

49

NSDecimalNumberNSNumber的子类)具有您正在寻找的所有好东西:

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

...

如果您对计算性能感兴趣,请转换为C ++数组std :: vector或类似物。

现在,我不再使用C-Arrays。使用错误的索引或指针崩溃很容易。将每个新[]与delete []配对非常麻烦。


您能否详细说明“将每个新[]与delete []配对非常繁琐”的含义?
jpswain 2011年

让我们这样说。在c中,完全避免使用指针。Objective-C的全部要点是让您不必担心的C之上放上一层。C不是直接使用的语言。首先需要对它进行“管理”。
user4951 2012年

加2后NSDecimalNumber,如何将NSDecimalNumber结果转换 回NSNumber?(这个问题是关于增加两个的NSNumberS,不增加两个NSDecimalNumber秒)
ohho

为什么总要有向量时为什么要使用C数组?
杰克·隆

1
为什么要将NSDecimalNumber转换回NSNumber?NSDecimalNumberNSNumber:@interface NSDecimalNumber : NSNumber
Steven Fisher

12

您可以使用

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

编辑:正如ohho所观察到的,此示例用于将两个NSNumber保存整数值的实例相加。如果要加总两个NSNumber包含浮点值的,则应执行以下操作:

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

“ @”符号的原因是什么?我不确定我在这种情况下会做什么。
Mike Meyers

啊。我现在看到的是它的NSNumber文字,如下所述:stackoverflow.com/a/11120371/35723
Mike Meyers 2013年

是的,@mikemeyers它的字面是包装像元intlong或它的大哥哥typedef“编NSIntegerNSNumber 的对象
克星

integerValue截断float。如何回答这个答案?
ohho 2014年

@ohho这是一个简单的示例。integerValue如果想保留数字的小数部分,为什么还要使用世界呢?
克星

6

当前投票最多的答案将导致难以诊断的错误,以及由于使用浮点数而导致的精度损失。如果要对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

为什么不使用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"

您还可以构建一个NSExpression,该NSExpression可以重复使用以使用不同的参数求值,如下所示:

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]);
 }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.