Si j'ai un nsarray code> de nsnumber code> Objets, comment calculer l'écart type des numéros dans le tableau? P>
6 Réponses :
Voici un lien à un algorithme que vous pouvez utiliser. Je ne connais pas de bibliothèques de statistiques sur l'objectif C intégrées, alors je voudrais simplement mettre en œuvre l'algorithme moi-même. Le lien le fait en Java, mais il devrait être facile de convertir. P>
Il y a un bon code sur Code Rosetta pour cela. Pour traverser votre Nsarray (au lieu de CARE C comme si elles ont dans leur exemple), utilisez simplement ce code avec leur implémentation de 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;
}
en supposant qu'il soit sûr de traiter tous les nsnumbers comme des flotteurs à double longueur (vous perdrez donc une certaine précision si vous avez des entiers 64 bits à des extrémités extrêmes de la plage de la plage) et je me suis souvenu de la formule correctement La mise en œuvre pourrait être:
- (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])];
}
+1 Dang, tu m'as battu. Si vous avez besoin de précision supérieure à un double code>, vous pouvez toujours passer à nsdecimal code>. Ce serait plus lent, mais tel est le prix de la précision. :)
N'oubliez pas de faire des sumofsquareddiFérences / ([Nombre de tableau] - 1) Si c'est un écart d'échantillon: P
Pourquoi iTERE deux fois? somme (1, n) (xi-m) ^ 2 == somme (1, n) xi ^ 2 - (somme (1, n) xi) ^ 2 / n ainsi itérer une fois accumuler une somme et une somme des carrés. (C'est la façon dont une calculatrice est-elle.) OK sa probablement une petite optimisation pour les petits tableaux, mais pour une méthode des statistiques fréquemment utilisées ... Si vous êtes vraiment préoccupé par la précision Consultez Knuth.
Aucune raison de la double itération; le tien serait certainement une amélioration. Pour la précision, je supposerais que dans une demande réelle, vous auriez une meilleure idée de quel type de nombre vous emballez dans les Numbers et à quel type de précision vous avez besoin.
Ancienne réponse, mais de toute façon, un autre raffinement: la première itération peut être remplacée par: nsnumber * moyenne = [Valeur de réseauPORKEYPATH: @ "@ avg.elf"]; code>
Et la deuxième itération peut être remplacée par: nsnumber * stddev = [VALEUR VALEUREYPATH: @ "@ stddev.elf"]; code>
Voici une autre version que j'ai utilisée il y a quelque temps.
Vous pouvez utiliser nsexpression code> Fonctions intégrées. 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...
Réponse vraiment intelligente!
Je pense que c'est la meilleure réponse
STDDEV: a des problèmes de précision lorsque 0 est l'un des éléments de la matrice. Être correct STDDEV calcule "écart type de la population" et ne pas échantillonner de déviation standard
C'est une bonne réponse! Seulement, j'ai essayé à la fois la nsexpression et le calcul direct (moyenne, alors somme des carrés de différences de moyenne, puis de la variance, puis de STDDEV --- toutes en double, mais pour une raison quelconque, il existe une écart non standard dans le résultat. ... Dans mon cas, (Sere 6 numéros) la différence entre 1,82 (calcul) et 1,94 (nsexpression). Qui croire?
Voici une catégorie de Nsarray pour faciliter des tâches similaires, en utilisant une nsexpression, similaire à la méthode de Tiago. Vous pouvez transmettre une norme Nsexpression que vous souhaitez calculer en tant que chaîne (le côlon est ajouté dans la fonction).
NSNumber *result = [myArray calculateStat:@"stddev"];
Nice Trick Kinky pour obtenir la nsexpression Fonctions internes "Out" à l'interface Array. En fait, vous pourriez aller plus loin et @Dynamic Ally ajoutez (en runtime) ces méthodes pour Nsarray, de manière générique ... donc "stddev" apparaîtrait comme [myarray stddev];