Obj-C: Calculate the standard deviation of an NSArray of NSNumber objects?

前端 未结 6 1708
心在旅途
心在旅途 2020-12-28 21:04

If I have an NSArray of NSNumber objects, how do I calculate the standard deviation of the numbers in the array?

相关标签:
6条回答
  • 2020-12-28 21:22

    You can use NSExpression built-in functions.

    NSArray *numbers = @[@1, @2, @3, @4, @5, @6, @7, @8];
    NSExpression *expression = [NSExpression expressionForFunction:@"stddev:" arguments:@[[NSExpression expressionForConstantValue:numbers]]];
    NSNumber *value = [expression expressionValueWithObject:nil context:nil];
    NSLog(@"%@,", value); // => 2.29128...
    

    For more information check the official documentation and this NSHipster article.

    0 讨论(0)
  • 2020-12-28 21:28

    Here a category for NSArray to facilitate similar tasks, using NSExpression, similar to Tiago's method. You can pass it any NSExpression that you wish to calculate as string (colon is added in the function).

    @interface NSArray (Stats)
    
    - (NSNumber *)calculateStat:(NSString *)stat;
    
    @end
    
    @implementation NSArray (Stats)
    
    - (NSNumber *)calculateStat:(NSString *)stat
    {
        NSArray *args = @[[NSExpression expressionForConstantValue:self]];
        NSString *statFormatted = [stat stringByAppendingString:@":"];
        NSExpression *expression = [NSExpression expressionForFunction:statFormatted arguments:args];
        return [expression expressionValueWithObject:nil context:nil];
    }
    
    @end
    

    Use like so:

    NSNumber *result = [myArray calculateStat:@"stddev"];
    
    0 讨论(0)
  • 2020-12-28 21:29

    There is some good code on Rosetta Code for this. To go through your NSArray (instead of C array like they have in their example), just use this code along with their implementation of SDAccum:

    - (double)computeStandardDeviationWithArray:(NSArray *)numberArray
    {
        double sd;
        SDAccum *sdacc = [[SDAccum alloc] init];
    
        for(NSNumber *aNumber in numberArray)
        {
            sd = [sdacc value: [aNumber doubleValue]];
        }
    
        [sdacc release];
        return sd;
    }
    
    0 讨论(0)
  • 2020-12-28 21:38

    Here is another version I've used some time ago.

    NSArray *numbers = [NSArray arrayWithObjects:[NSNumber numberWithInt:...],
                                                 [NSNumber numberWithInt:...],
                                                 [NSNumber numberWithInt:...], nil];
    
    // Compute array average
    int total = 0;
    int count = [numbers count];
    
    for (NSNumber *item in numbers) {
    
        total += [item intValue];
    }
    
    double average = 1.0 * total / count;
    
    // Sum difference squares
    double diff, diffTotal = 0;
    
    for (NSNumber *item in numbers) {
    
        diff = [item doubleValue] - average;
        diffTotal += diff * diff;
    }
    
    // Set variance (average from total differences)
    double variance = diffTotal / count; // -1 if sample std deviation
    
    // Standard Deviation, the square root of variance
    double stdDeviation = sqrt(variance);
    
    0 讨论(0)
  • 2020-12-28 21:42

    Assuming it's safe to process all NSNumbers as double length floats (so you'll lose some precision if you've got some 64 bit integers at extreme ends of the range in there) and I've remembered the formula correctly a first implementation could be:

    - (NSNumber *)meanOf:(NSArray *)array
    {
        double runningTotal = 0.0;
    
        for(NSNumber *number in array)
        {
            runningTotal += [number doubleValue];
        }
    
        return [NSNumber numberWithDouble:(runningTotal / [array count])];
    }
    
    - (NSNumber *)standardDeviationOf:(NSArray *)array
    {
        if(![array count]) return nil;
    
        double mean = [[self meanOf:array] doubleValue];
        double sumOfSquaredDifferences = 0.0;
    
        for(NSNumber *number in array)
        {
             double valueOfNumber = [number doubleValue];
             double difference = valueOfNumber - mean;
             sumOfSquaredDifferences += difference * difference;
        }
    
        return [NSNumber numberWithDouble:sqrt(sumOfSquaredDifferences / [array count])];
    }
    
    0 讨论(0)
  • 2020-12-28 21:48

    Here's a link to an algorithm you could use. I don't know of any built-in Objective C statistics libraries, so I would just implement the algorithm myself. The link does it in Java, but it should be easy to convert.

    0 讨论(0)
提交回复
热议问题