2011-02-03 12 views

答えて

23

それは、二重の長さの山車としてすべてNSNumbersを処理しても安全です(だからと仮定すると、 「可能性がありますが、そこでの範囲の両極端で、いくつかの64ビット整数を持っている場合、一部の精度を失うLL)と私が正しく式最初の実装を思い出しました:

- (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

1一顧は、あなたはそれに私を打ちます。 'double'よりも高い精度が必要な場合、いつでも' NSDecimal'に切り替えることができます。それは遅くなりますが、そのような精度の価格です。 :) –

+0

ありがとう!それは魅力のように働く。 – Clay

+1

サンプル偏差の場合、sumOfSquaredDifferences /([配列数] - 1)を実行するのを忘れないでください:P – sidyll

0

使用できるアルゴリズムにはlinkがあります。私は組み込みのObjective C統計ライブラリを知らないので、アルゴリズムを自分で実装するだけです。リンクはJavaで行いますが、変換は簡単です。

0

これにはRosetta Codeにいくつかの良いコードがあります。 (彼らは彼らの例では持っているように代わりにC配列の)あなたにNSArrayを通過するには、ちょうど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

ここで私は別のバージョンである」は、以前は何度か使用されていました。

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); 
24

NSExpression組み込み関数を使用できます。

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... 

詳細については、公式documentationと、このNSHipster articleを確認してください。

+1

本当に賢い答え! –

+1

私はこれが最高の答えだと思う。 – Zee

+0

stddev:0が配列の要素の1つである場合、精度の問題がある。正確であるためには、標準偏差のサンプルではなく、「母集団標準偏差」を計算する – Dhilip

1

ここでは、NSArrayのカテゴリで、NSExpressionを使用して同様のタスクを容易にすることができます。これは、Tiagoの方法と同様です。文字列としてany NSExpression that you wish to calculateを渡すことができます(関数内にコロンが追加されています)。

@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 

そうのような使用:

NSNumber *result = [myArray calculateStat:@"stddev"]; 
関連する問題