对double执行算术运算

时间:2014-03-23 19:17:20

标签: ios double nsdecimalnumber

我有一个应用程序,其目的是比较按时间顺序排列的时间间隔,这些时间间隔由Core Data(通过MagicalRecord)存储为double类型的属性,名为TimedActivity。订购方向由名为activityOfInterest的另一个实体上名为benchmarkActivitySearchSpecs的属性提供。这个计划可能看起来有点过于复杂,因为我很绿,但这一部分都有效。

问题在于,从两个双打中获得百分比似乎是一个小问题,至少根据我所做的研究。我不需要极高的精确度。圆秒就可以了。我发现了一个与使用NSDecimalNumber有关的建议,但它似乎还有很长的路要走。

以下是相关代码的当前状态,伪代码表示我的问题区域:

#pragma mark - Go button case handlers

-(void) handleAvsAAction
{
//    NSArray *searchSpecsObjects = [SearchSpecs MR_findAll];
//    NSLog(@"SearchSpecs number of objects is %i",[searchSpecsObjects count]);

    NSArray *searchSpecsArray = [SearchSpecs MR_findAll];
    NSLog(@"searchSpecsArray count is %i", [searchSpecsArray count]);

    SearchSpecs *thisSpec = [searchSpecsArray objectAtIndex:0];
    NSLog(@"SearchSpec activityOfInterest should be %@", thisSpec.activityOfInterest);
    NSLog(@"SearchSpec benchmarkActivity should be %@", thisSpec.benchmarkActivity);

    //    NSArray *activityOfInterestArray;
//    NSArray *benchmarkActivityArray;
    NSNumber *activityOfInterestDurationTotal;
    NSNumber *benchmarkActivityDurationTotal;

    NSPredicate *activityOfInterestPredicate = [NSPredicate predicateWithFormat:@"name == '%@'",thisSpec.activityOfInterest];

    NSPredicate *benchmarkActivityPredicate = [NSPredicate predicateWithFormat:@"name == '%@'", thisSpec.benchmarkActivity];

    activityOfInterestDurationTotal = [TimedActivity MR_aggregateOperation:@"sum:" onAttribute:@"duration" withPredicate:activityOfInterestPredicate];
    NSLog(@"The sum of all the durations for the activity of interest is %zd", activityOfInterestDurationTotal);

    benchmarkActivityDurationTotal = [TimedActivity MR_aggregateOperation:@"sum:" onAttribute:@"duration" withPredicate:benchmarkActivityPredicate];
    NSLog(@"The sum of all the durations for the benchmark activity is %zd", benchmarkActivityDurationTotal);

    [self doTheMathAvsA];

}

-(void) doTheMathAvsA
{
    // Get the total and respective percentages of the totalled durations from the criteria distilled in handleAvsAAction

NSNumber *total;
total = (activityOfInterestDurationTotal + benchmarkActivityDurationTotal);

}

修改修改doTheMathAvsA以澄清所需的结果。

所有帮助或建议表示赞赏!

第二次修改:

好的,下面你的答案是有道理的,谢谢@Martin R!

但是,此处讨论的两个数量源自NSTimeInterval,如上所述,在double的实体上存储为TimedActivity类型的属性。

所以,稍微重写代码以将其作为NSTimeInterval s从持久性存储中提取出来似乎是理性的,我确信这些代码实际上只是双倍的。但是,当我这样做时,我收到此错误:

Assigning to 'NSTimeInterval' (aka 'double') from incompatible type 'NSNumber *'

以下是修改过的声明:

NSTimeInterval activityOfInterestDurationTotal;
NSTimeInterval benchmarkActivityDurationTotal;

此处出现错误:

activityOfInterestDurationTotal = [TimedActivity MR_aggregateOperation:@"sum:" onAttribute:@"duration" withPredicate:activityOfInterestPredicate];
NSLog(@"The sum of all the durations for the activity of interest is %@", activityOfInterestDurationTotal);

benchmarkActivityDurationTotal = [TimedActivity MR_aggregateOperation:@"sum:" onAttribute:@"duration" withPredicate:benchmarkActivityPredicate];
NSLog(@"The sum of all the durations for the benchmark activity is %@", benchmarkActivityDurationTotal);

好的,我假设错误消息中引用的NSNumberTimedActivity托管对象子类中的此属性,是从数据模型自动生成的:

@property (nonatomic, retain) NSNumber * duration;

所以我的问题变成了:

是否真的有必要求助于这些看似不断扩大的转换和复古转换圈来执行这样一个看似简单的计算?或者我错过了一个更简单的解决方案?

谢谢!

1 个答案:

答案 0 :(得分:2)

您无法直接对NSNumber个对象执行算术运算。最简单的解决方案是 将它们转换为double以进行添加:

double tmp = [activityOfInterestDurationTotal doubleValue] + [benchmarkActivityDurationTotal doubleValue];

,如有必要,结果返回NSNumber

NSNumber *total = @(tmp);

更新:默认情况下,Xcode生成的访问器方法甚至使用Objective-C对象 对于原始核心数据类型,例如" Double"。您可以通过选择更改它 "对原始数据类型使用标量属性"创建子类文件时的选项。 然后是" Double"属性声明为

@property (nonatomic) double activityOfInterestDurationTotal;

你可以直接访问它""例如

NSTimeInterval duration = thisActivity.duration;

因为NSTimeInterval只是double的另一个名称。

还有另一个问题:MagicalRecord"便利方法" MR_aggregateOperation:使用NSDictionaryResultType的特殊抓取请求 获取所有duration值的总和。即使你选择使用标量属性 对于持续时间,MR_aggregateOperation:的结果总是一些Objective-C对象,在这种情况下NSNumber,没有办法解决它。

因此,避免NSNumberdouble之间转换的唯一方法是使用标量 如上所述的属性,而不是使用MR_aggregateOperation:,获取所有 对象并在一个简单的循环中自己添加duration值。

但请注意,使用聚合操作的提取请求会执行计算 在SQLite级别上,这可能比实际获取所有对象更有效。