Ios 如何将核心数据中每个对象的十进制值相加,得出一个总数?

Ios 如何将核心数据中每个对象的十进制值相加,得出一个总数?,ios,objective-c,cocoa-touch,core-data,nsdecimalnumber,Ios,Objective C,Cocoa Touch,Core Data,Nsdecimalnumber,我试图做的是循环遍历我的核心数据对象,并添加每个项目的价格,然后返回总数。我下面的代码不断崩溃,我不知道为什么。以前我使用浮点数,但有人建议我使用NSDecimalNumber,因为它更准确。所以我开始转换我的代码来使用它 循环对象并添加价格然后返回总计的代码: + (NSDecimalNumber *)totalPriceOfItems:(NSManagedObjectContext *)managedObjectContext { NSError *error = nil;

我试图做的是循环遍历我的核心数据对象,并添加每个项目的价格,然后返回总数。我下面的代码不断崩溃,我不知道为什么。以前我使用浮点数,但有人建议我使用NSDecimalNumber,因为它更准确。所以我开始转换我的代码来使用它

循环对象并添加价格然后返回总计的代码:

+ (NSDecimalNumber *)totalPriceOfItems:(NSManagedObjectContext *)managedObjectContext
{
    NSError *error = nil;
    NSDecimalNumber *totalPrice = [[NSDecimalNumber alloc] init];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"BagItem"];

    // Get fetched objects and store in NSArray
    NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

    for (BagItem *bagItem in fetchedObjects) {

     //   NSDecimalNumber *price = [NSDecimalNumber decimalNumberWithString:[bagItem price]];
      //  NSString *price = [[[bagItem price] componentsSeparatedByCharactersInSet:
          //                  [[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
            //               componentsJoinedByString:@""];
       totalPrice = [totalPrice decimalNumberByAdding:[bagItem price]];

        NSLog(@"total: %@", totalPrice);
    }

    return totalPrice;
}
** Terminating app due to uncaught exception 'NSDecimalNumberOverflowException', reason: 'NSDecimalNumber overflow exception'
*** First throw call stack:
错误:

+ (NSDecimalNumber *)totalPriceOfItems:(NSManagedObjectContext *)managedObjectContext
{
    NSError *error = nil;
    NSDecimalNumber *totalPrice = [[NSDecimalNumber alloc] init];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"BagItem"];

    // Get fetched objects and store in NSArray
    NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

    for (BagItem *bagItem in fetchedObjects) {

     //   NSDecimalNumber *price = [NSDecimalNumber decimalNumberWithString:[bagItem price]];
      //  NSString *price = [[[bagItem price] componentsSeparatedByCharactersInSet:
          //                  [[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
            //               componentsJoinedByString:@""];
       totalPrice = [totalPrice decimalNumberByAdding:[bagItem price]];

        NSLog(@"total: %@", totalPrice);
    }

    return totalPrice;
}
** Terminating app due to uncaught exception 'NSDecimalNumberOverflowException', reason: 'NSDecimalNumber overflow exception'
*** First throw call stack:

我不知道为什么会出现溢出,因为
NSDecimal
的范围比
浮点的范围大(不过它没有
双精度的范围大)

不管是什么原因,滚动自己的循环并不是从核心数据请求聚合结果的正确方法:只要代码提供有关如何聚合数据的正确说明,API允许您请求数据库为您合计价格。您应该能够通过传递聚合表达式直接从核心数据中获取总计,如下所示:

NSExpression *totalPriceExpr = [NSExpression expressionForFunction:@"sum:"
    arguments:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:@"Price"]]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"totalPrice"];
[expressionDescription setExpression:totalPriceExpr];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"BagItem"];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

fetchedObjects
将包含一个带有计数的项目。

我不确定为什么会出现溢出,因为
NSDecimal
的范围大于
float
(但它没有
双精度
的范围宽)

不管是什么原因,滚动自己的循环并不是从核心数据请求聚合结果的正确方法:只要代码提供有关如何聚合数据的正确说明,API允许您请求数据库为您合计价格。您应该能够通过传递聚合表达式直接从核心数据中获取总计,如下所示:

NSExpression *totalPriceExpr = [NSExpression expressionForFunction:@"sum:"
    arguments:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:@"Price"]]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"totalPrice"];
[expressionDescription setExpression:totalPriceExpr];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"BagItem"];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

fetchedObjects
将包含一个带有计数的项目。

获取的例外情况是,您试图添加两个非常大的数字,而表示该数字所需的位数对于NSDecimalNumber来说太大。您的数字可能不是问题所在,而是您声明totalPrice变量的方式

这一行应该改一下

NSDecimalNumber *totalPrice = [[NSDecimalNumber alloc] init];

NSDecimalNumber是围绕NSDecimal(本身围绕NSValue)的包装器,不为其init方法提供默认值。如果它真的这样做了,值应该是多少?一,零,十万?它实际上默认为NaN。本质上,您的起始值可能会占用所有可用字节,并且无论何时添加,都会得到异常


NSDecimalNumber内置了处理溢出和其他数学错误(例如被零除)的机制。您可以通过使用setBehavior方法调用提供新的行为对象来更改默认行为。

您得到的例外情况是,您试图添加两个非常大的数字,而表示它所需的位数对于NSDecimalNumber来说太大。您的数字可能不是问题所在,而是您声明totalPrice变量的方式

这一行应该改一下

NSDecimalNumber *totalPrice = [[NSDecimalNumber alloc] init];

NSDecimalNumber是围绕NSDecimal(本身围绕NSValue)的包装器,不为其init方法提供默认值。如果它真的这样做了,值应该是多少?一,零,十万?它实际上默认为NaN。本质上,您的起始值可能会占用所有可用字节,并且无论何时添加,都会得到异常


NSDecimalNumber内置了处理溢出和其他数学错误(例如被零除)的机制。您可以通过使用setBehavior方法调用提供新的行为对象来更改默认行为。

NSDecimalNumber*totalPrice=[[NSDecimalNumber alloc]initWithInt:0];为我工作过。NSDecimalNumber*totalPrice=[[NSDecimalNumber alloc]initWithInt:0];为我工作,很有帮助。没有意识到核心数据能够做到这一点。非常有用。没有意识到核心数据能够做到这一点。