如何在核心数据中添加每个对象的十进制值以得出总数?

Posted

技术标签:

【中文标题】如何在核心数据中添加每个对象的十进制值以得出总数?【英文标题】:How do I add decimal values of each object in core data to come up with a total? 【发布时间】:2014-07-06 22:13:07 【问题描述】:

我要做的是遍历我的核心数据对象并添加每个项目的价格并返回该总数。我的以下代码不断崩溃,我不知道为什么。以前我使用浮点数,但有人建议我使用 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:

【问题讨论】:

【参考方案1】:

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

这行应该改

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

NSDecimalNumber *totalPrice = [NSDecimalNumber zero];

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

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

【讨论】:

NSDecimalNumber *totalPrice = [[NSDecimalNumber alloc] initWithInt:0];为我工作。【参考方案2】:

我不确定您为什么会出现溢出,因为NSDecimal 的范围大于float 的范围(虽然它没有double 的范围那么宽)。

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

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 将包含一个带有计数的项目。

【讨论】:

非常有帮助。没有意识到核心数据能够做到这一点。

以上是关于如何在核心数据中添加每个对象的十进制值以得出总数?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取每个分区的最后一个值以在 Spark SQL 中估算缺失值

在 for 循环中添加整数并打印总数

核心数据多实体

Core Data 在 fetchObjects 中保留两个对象而不是 27 个

如何使用react将多个参数作为url中的对象传递

用于向表中添加新行的存储过程,它检查值以验证它们在外部表上的值