2013-03-13 2 views
0

J'ai un NSMutableArray qui ont une NSDecimalNumber en elle, comme (500,50.80,70,8000)Comment ajouter tous les nombres décimaux dans un NSMutableArray

Maintenant, je veux ajouter tous ceux decimal numbers ensemble.

J'ai essayé d'utiliser

for (NSDecimalNumber *number in self.numbersArray) 
{ 
    NSDecimal *sum += [number decimalValue] 
} 

, mais a échoué.

+0

Si votre tableau contient des dictionnaires alors Apple fournit une seule ligne d'exécution NSNumber * amountSum = [YourArray valueForKeyPath: @ "@ sum.amount"]; NSLog (@ "% @", amountSum); –

+0

pour plus d'informations, vous pouvez passer par ce lien http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueCoding/Articles/CollectionOperators.html –

+0

@Manohar: Vous pouvez utiliser KVC également pour une plaine tableau: '[myArray valueForKeyPath: @" @ sum.self "]'. –

Répondre

2

Utilisez - (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber

Jetez un oeil à NSDecimalNumber Class Reference

NSDecimalNumber *lNumber = [NSDecimalNumber zero]; 
for (NSDecimalNumber *number in self.numbersArray) 
{ 
    lNumber = [lNumber decimalNumberByAdding:number]; 
} 
+0

Merci c'est ce dont j'ai besoin! –

1

suggestion de Manohar dans les commentaires est pas mal. Vous pouvez en effet utiliser KVC collection operators pour créer un doublage: [myArray valueForKeyPath:@"@sum.doubleValue"];, mais vous risquez de perdre de la précision (en fonction des numéros que vous avez stockés).

Vous recherchez essentiellement la fonctionnalité "réduire"; vous devez chaîner les appels à decimalNumberByAdding: afin que chaque appel ait comme argument l'élément suivant du tableau. Faire cela sur un NSArray est assez facile, en utilisant performSelector:withObject:

@implementation NSArray (Reduce) 
- (id)reduceUsingSelector: (SEL)sel 
{ 
    id res = [self objectAtIndex:0]; 
    for(id obj in [self subarrayWithRange:(NSRange){1, [self count]-1}]){ 
     res = [res performSelector:sel withObject:obj]; 
    } 

    return res; 
} 
@end 

Utilisez ce comme ceci: NSDecimalNumber * sum = [myArray reduceUsingSelector:@selector(decimalNumberByAdding:)];

Le code que vous avez échoue parce NSDecimal est un struct, pas un objet; il ne devrait pas être déclaré comme un pointeur, et si ce n'était pas le cas, vous ne seriez pas en mesure de l'ajouter. Ce n'est pas la bonne voie vers une solution.

+0

+1: bel exemple d'une méthode de commande supérieure – vikingosegundo

+1

J'ai fixé le paramètre de longueur pour le sous-réseau, j'espère que c'est OK. –

+0

Remarque: '[myArray valueForKeyPath: @" sum.self "]' fonctionne également et renvoie un objet NSDecimalNumber, mais je ne sais pas si NSDecimalNumber est utilisé pour tous les calculs intermédiaires. –

5

Une façon simple d'ajouter tous les NSNumber s dans un tableau est (semblable à ce que @Mahonor dit dans un commentaire):

NSArray *myArray = ... // array of NSNumber (or NSDecimalNumber) objects 
NSNumber *sum = [myArray valueForKeyPath:@"@sum.self"]; 

Contrairement à ce que les États Collection Operators: sum, les chiffres du tableau pas converti en double, mais en NSDecimal. Par conséquent, aucune précision n'est perdue lors de l'ajout de nombres décimaux. Même les objets NSNumber qui ne sont pas des nombres décimaux sont convertis en NSDecimal pour l'addition. Le résultat de la sommation est une instance de NSDecimalValue.

J'ai vérifié (ou essayé de le faire) de deux manières différentes. Tout d'abord, j'ai couru ce code

NSNumber *a = [NSNumber numberWithDouble:1.2]; 
NSNumber *b = [NSDecimalNumber decimalNumberWithString:@"-5.7"]; 
NSArray *myArray = @[a, b]; 
id sum = [myArray valueForKeyPath:@"@sum.self"]; 

et activé la journalisation des messages Objective-C en définissant la variable d'environnement "NSObjCMessageLoggingEnabled = OUI". Comme on peut le voir dans le fichier "/ tmp/msgSends-NNNN" créé, decimalNumber (et non doubleValue) est envoyé aux deux objets numériques.

Deuxièmement, je créé une classe personnalisée mise en œuvre à la fois decimalValue et doubleValue et appliqué @sum.self à un tableau d'objets de la classe personnalisée:

@interface MyClass : NSObject 
@property (nonatomic, assign) double value; 
@end 

@implementation MyClass 

- (NSDecimal)decimalValue 
{ 
    return [[NSNumber numberWithDouble:self.value] decimalValue]; 
} 

- (double)doubleValue 
{ 
    return self.value; 
} 

@end 

MyClass *a = [MyClass new]; a.value = 1.2; 
MyClass *b = [MyClass new]; b.value = -5.7; 
NSArray *myArray = @[a, b]; 
id sum = [myArray valueForKeyPath:@"@sum.self"]; 

En définissant des points d'arrêt dans les deux méthodes, on voit que seulement decimalValue est utilisé pour la sommation (et valueForKeyPath:@"@sum.self" lève une exception si la classe n'implémente pas decimalValue).

On peut aussi voir que decimalValue est appelé à partir

-[NSArray(NSKeyValueCoding) _sumForKeyPath:] 

et le code assembleur pour cette méthode montre que NSDecimalAdd est utilise pour ajouter les numéros.

+1

Très belle recherche! Toujours génial d'apprendre quelque chose de nouveau sur les rouages ​​internes. –

Questions connexes