7
votes

Number Comparer: Renvoyer différents résultats

J'essaie de faire des comparaisons de nombre et je reçois des résultats étranges.

NSNumber* number1 = [NSNumber numberWithFloat:1.004];
NSNumber* number2 = [NSNumber numberWithDouble:1.004];

([number1 compare:number2] == NSOrderedSame) ? NSLog(@"YES") : NSLog(@"NO");
([number1 compare:number2] == NSOrderedAscending) ? NSLog(@"YES") : NSLog(@"NO");
([number1 doubleValue] == [number2 doubleValue]) ? NSLog(@"YES") : NSLog(@"NO");
([number1 floatValue] == [number2 floatValue]) ? NSLog(@"YES") : NSLog(@"NO");


2 commentaires

Qu'en est-il de si vous utilisez [Number1 isequaltonumber: numéro2] , c'est la voie préférée, au moins si vous n'essayez pas de déterminer l'égalité des valeurs?


Désolé Twilson, qui retourne toujours non. Les chiffres sont différents.


4 Réponses :


2
votes

Le comparateur: la méthode suit les règles Standard C pour la conversion de type. Par exemple, si vous comparez un objet NSNumber comportant une valeur entière avec un objet NSNumber comportant une valeur de point flottante, la valeur entière est convertie en une valeur à virgule flottante pour la comparaison.

Aussi, initialisation d'un nombre de nsnumber avec un flotteur , puis la convertir en un double perd une certaine précision. P>

NSNumber* number1 = [NSNumber numberWithFloat:1.004];
NSNumber* number2 = [NSNumber numberWithDouble:1.004];
NSLog(@"number1 double: %1.16f", [number1 doubleValue]);
NSLog(@"number2 double: %1.16f", [number2 doubleValue]);
NSLog(@"number1 objCType %s", [number1 objCType]);
NSLog(@"number2 objCType %s", [number2 objCType]);

2012-02-09 15:59:49.487 testNSNumber[89283:f803] number1 double: 1.0039999485015869
2012-02-09 15:59:49.488 testNSNumber[89283:f803] number2 double: 1.0040000000000000
2012-02-09 16:21:01.655 testNSNumber[4351:f803] number1 objCType f
2012-02-09 16:21:01.656 testNSNumber[4351:f803] number2 objCType d


1 commentaires

J'aime beaucoup cet objtype! Merci!



2
votes

Veuillez essayer le iSeequaltonumber : méthode pour vérifier votre condition xxx

Cette question Stackoverflow donne également une réponse détaillée


1 commentaires

Cela ne fonctionnera pas comme prévu et va connecter "non". Les nsnumbers initialisés avec flotteur et doubles seront des valeurs différentes. Voir ma réponse ci-dessus. La question de la question que vous référence utilise tous les floattes.



7
votes

J'ai essayé d'utiliser isequaltonumber: et il a renvoyé non. La raison pour laquelle ils ne sont pas identiques sont parce que 1,004 ne peut pas être représenté exactement en binaire. L'approximation double a plus de chiffres après le point décimal que l'approximation float afin que les deux chiffres soient différents. Normalement, lorsque vous comparez des nombres de points flottants, vous testez pour voir s'ils sont égaux à une valeur de tolérance fabs (a - b) : xxx

résultats: xxx


4 commentaires

Très bonne solution! Il me semble fou de moi que Apple ne gère pas cela avec le comparateur: méthode ...


Apple (ou, plus précisément, les écrivains du compilateur) ne peuvent pas faire d'hypothèses sur la tolérance du programmeur pour l'égalité. Tout ce qu'ils peuvent faire, c'est exactement ce que le programmateur leur a dit de faire. Dans ce cas, vous compariez deux valeurs inégales. Les nombres de points flottants ne sont pas un sujet trivial. Si vous avez un peu de temps, jetez un coup d'œil à Ce que chaque informatique devrait Connaître l'arithmétique de points flottants .


Merci pour la référence! Je cherchais une lecture recommandée à ce sujet. J'ai su sur cette question pendant un moment, je n'ai rien fait de rien à ce sujet. :)


C'est la bonne solution, mais j'ajouterais que cela pourrait être rendu plus lisible en regroupant cet algorithme simple dans A - [Nsnumber Isequaltonumber: Fustolérance:] Méthode dans une catégorie de classe.



0
votes

Une autre solution qui a fonctionné pour moi était de les convertir en Nstrings et de faire une comparaison de chaînes. C'était parce que je travaille avec des prix décimaux à 4 chiffres et cela a bien fonctionné pour moi. XXX

Ceci s'est débarrassé de la question où je comparais un double avec 2 zéros traînants et un float sans zéros. .

J'avais normalement mis en garde contre les comparaisons de cordes comme celle-ci, mais comme mes règles ont toujours été réparées, c'était ok pour moi dans ce cas.


0 commentaires