我有一个NSMutableArray
里面有一些NSDecimalNumber
,比如(500,50.80,70,8000)
现在我想把所有这些加decimal numbers
在一起。
我试过用
for (NSDecimalNumber *number in self.numbersArray)
{
NSDecimal *sum += [number decimalValue]
}
但是失败了。
我有一个NSMutableArray
里面有一些NSDecimalNumber
,比如(500,50.80,70,8000)
现在我想把所有这些加decimal numbers
在一起。
我试过用
for (NSDecimalNumber *number in self.numbersArray)
{
NSDecimal *sum += [number decimalValue]
}
但是失败了。
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
用于添加数字。
利用- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber
NSDecimalNumber *lNumber = [NSDecimalNumber zero];
for (NSDecimalNumber *number in self.numbersArray)
{
lNumber = [lNumber decimalNumberByAdding:number];
}
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
它是一个结构,而不是一个对象;它不应该被声明为指针,如果不是,您将无法添加它。这不是解决问题的正确途径。