web-dev-qa-db-fra.com

Comment ajouter deux objets NSNumber?

Cela doit maintenant être facile, mais comment peut-on résumer deux NSNumber? Est comme:

[one floatValue] + [two floatValue]

ou existe une meilleure façon?

74
mamcx

Il n'y a pas vraiment de meilleur moyen, mais vous ne devriez vraiment pas le faire si vous pouvez l'éviter. NSNumber existe en tant que wrapper pour les nombres scalaires afin que vous puissiez les stocker dans des collections et les transmettre de manière polymorphe avec une autre NSObjects. Ils ne sont pas vraiment utilisés pour stocker des nombres en mathématiques réelles. Si vous faites des calculs avec eux, il est beaucoup plus lent que d'effectuer l'opération uniquement sur les scalaires, ce qui explique probablement pourquoi il n'existe aucune méthode pratique pour le calculer.

Par exemple:

NSNumber *sum = [NSNumber numberWithFloat:([one floatValue] + [two floatValue])];

Souffle au minimum 21 instructions sur les envois de messages, et quel que soit le code utilisé par les méthodes pour décompresser et redistribuer les valeurs (probablement quelques centaines) afin d'effectuer une instruction valant mathématique.

Ainsi, si vous avez besoin de stocker des nombres dans dict, utilisez une NSNumber, si vous devez transmettre quelque chose qui pourrait être un nombre ou une chaîne à une fonction, utilisez un NSNumber, mais si vous voulez simplement utiliser le calcul mathématique avec des types C scalaires.

138
Louis Gerbarg

NSDecimalNumber (sous-classe de NSNumber ) a tous les goodies que vous recherchez:

– decimalNumberByAdding:
– decimalNumberBySubtracting:
– decimalNumberByMultiplyingBy:
– decimalNumberByDividingBy:
– decimalNumberByRaisingToPower:

...

Si les performances informatiques vous intéressent, convertissez-les en tableau C++ std :: vector ou similaire.

Maintenant, je n'utilise plus de C-Arrays; il est trop facile de planter en utilisant un index ou un pointeur incorrect. Et très fastidieux de jumeler chaque nouveau [] avec delete [].

48
Semmel

Vous pouvez utiliser

NSNumber *sum = @([first integerValue] + [second integerValue]);

Edit: Comme observé par ohho , cet exemple permet d’additionner deux instances NSNumber contenant des valeurs entières. Si vous souhaitez additionner deux NSNumber contenant des valeurs à virgule flottante, procédez comme suit:

NSNumber *sum = @([first floatValue] + [second floatValue]);
10
nemesis

La réponse actuelle de la plus votée va conduire à des bugs difficiles à diagnostiquer et à une perte de précision due à l'utilisation de float. Si vous effectuez des opérations sur les nombres avec les valeurs NSNumber, vous devez d'abord convertir en NSDecimalNumber, puis effectuer des opérations avec ces objets.

De la documentation :

NSDecimalNumber, une sous-classe immuable de NSNumber, fournit un encapsuleur orienté objet permettant d'effectuer l'arithmétique en base 10. Une instance peut représenter n’importe quel nombre pouvant être exprimé en mantisse x 10 ^ exposant, où mantisse est un entier décimal allant jusqu’à 38 chiffres et l’exposant est un entier compris entre –128 et 127.

Par conséquent, vous devez convertir vos instances NSNumber en NSDecimalNumbers au moyen de [NSNumber decimalValue], effectuer l’arithmétique de votre choix, puis réaffecter un NSNumber lorsque vous avez terminé.

En Objective-C:

NSDecimalNumber *a = [NSDecimalNumber decimalNumberWithDecimal:one.decimalValue]
NSDecimalNumber *b = [NSDecimalNumber decimalNumberWithDecimal:two.decimalValue]
NSNumber *result = [a decimalNumberByAdding:b]

Dans Swift 3:

let a = NSDecimalNumber(decimal: one.decimalValue)
let b = NSDecimalNumber(decimal: two.decimalValue)
let result: NSNumber = a.adding(b)
4
Dan Loewenherz

Pourquoi ne pas utiliser NSxEpression?

NSNumber *x = @(4.5), *y = @(-2);

NSExpression *ex = [NSExpression expressionWithFormat:@"(%@ + %@)", x, y];
NSNumber *result = [ex expressionValueWithObject:nil context:nil];

NSLog(@"%@",result); // will print out "2.5"

Vous pouvez également créer une expression NSExpression pouvant être réutilisée pour être évaluée avec différents arguments, comme ceci:

NSExpression *expr = [NSExpression expressionWithFormat: @"(X+Y)"];
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:x, @"X", y, @"Y", nil];
NSLog(@"%@", [expr expressionValueWithObject:parameters context:nil]);

Par exemple, nous pouvons analyser en boucle la même expression analysée, chaque fois avec une valeur "Y" différente:

 for (float f=20; f<30; f+=2.0) {
    NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:x, @"X", @(f), @"Y", nil];
    NSLog(@"%@", [expr expressionValueWithObject:parameters context:nil]);
 }
0
Motti Shneor

Dans Swift, vous pouvez obtenir cette fonctionnalité en utilisant la bibliothèque Bolt_Swift https://github.com/williamFalcon/Bolt_Swift

Exemple:

  var num1 = NSNumber(integer: 20)
  var num2 = NSNumber(integer: 25)
  print(num1+num2) //prints 45
0
William Falcon