1

我有一个NSMutableArray里面有一些NSDecimalNumber,比如(500,50.80,70,8000)

现在我想把所有这些加decimal numbers在一起。

我试过用

for (NSDecimalNumber *number in self.numbersArray)
{
    NSDecimal *sum += [number decimalValue]
}

但是失败了。

4

3 回答 3

5

NSNumber在数组中添加所有 s 的简单方法是(类似于@Mahonor 在评论中所说的):

NSArray *myArray = ... // array of NSNumber (or NSDecimalNumber) objects
NSNumber *sum = [myArray valueForKeyPath:@"@sum.self"];

Collection Operators: sum状态相反,数组中的数字不是转换为double,而是转换为NSDecimal。因此,添加十进制数时不会丢失精度。即使NSNumber不是十进制数的对象也会转换NSDecimal为加法。求和的结果是 的一个实例NSDecimalValue

我以两种不同的方式验证(或尝试)了这一点。首先,我运行了这段代码

NSNumber *a = [NSNumber numberWithDouble:1.2];
NSNumber *b = [NSDecimalNumber decimalNumberWithString:@"-5.7"];
NSArray *myArray = @[a, b];
id sum = [myArray valueForKeyPath:@"@sum.self"];

并通过设置环境变量“NSObjCMessageLoggingEnabled=YES”来激活 Objective-C 消息记录。从创建的“/tmp/msgSends-NNNN”文件中可以看出,decimalNumber(而不是doubleValue)被发送到两个数字对象。

其次,我创建了一个实现decimalValue和的自定义类doubleValue,并将其应用于@sum.self自定义类的对象数组:

@interface MyClass : NSObject
@property (nonatomic, assign) double value;
@end

@implementation MyClass

- (NSDecimal)decimalValue
{
    return [[NSNumber numberWithDouble:self.value] decimalValue];
}

- (double)doubleValue
{
    return self.value;
}

@end

MyClass *a = [MyClass new]; a.value = 1.2;
MyClass *b = [MyClass new]; b.value = -5.7;
NSArray *myArray = @[a, b];
id sum = [myArray valueForKeyPath:@"@sum.self"];

通过在这两种方法中设置断点,可以看出 onlydecimalValue用于求和(valueForKeyPath:@"@sum.self"如果类没有实现则抛出异常decimalValue)。

也可以看出decimalValue是从

-[NSArray(NSKeyValueCoding) _sumForKeyPath:]

并且此方法的汇编代码显示NSDecimalAdd用于添加数字。

于 2013-03-13T10:54:06.107 回答
3

利用- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber

看看NSDecimalNumber 类参考

NSDecimalNumber *lNumber = [NSDecimalNumber zero];
for (NSDecimalNumber *number in self.numbersArray)
{
    lNumber = [lNumber decimalNumberByAdding:number];
}
于 2013-03-13T06:53:29.460 回答
1

Manohar 在评论中的建议还不错。您确实可以使用KVC 集合运算符来制作单线:[myArray valueForKeyPath:@"@sum.doubleValue"];,但您可能会丢失精度(取决于您存储的数字)。

您基本上是在寻找“减少”功能;您需要链接调用,decimalNumberByAdding:以便每个调用都将数组的后续元素作为其参数。这样做NSArray很容易,使用performSelector:withObject:

@implementation NSArray (Reduce)
- (id)reduceUsingSelector: (SEL)sel
{
    id res = [self objectAtIndex:0];
    for( id obj in [self subarrayWithRange:(NSRange){1, [self count]-1}] ){
        res = [res performSelector:sel withObject:obj];
    }

    return res;
}
@end

像这样使用它:NSDecimalNumber * sum = [myArray reduceUsingSelector:@selector(decimalNumberByAdding:)];

您拥有的代码不成功,因为NSDecimal它是一个结构,而不是一个对象;它不应该被声明为指针,如果不是,您将无法添加它。这不是解决问题的正确途径。

于 2013-03-13T07:11:03.050 回答