2016-08-24 1 views
8

Pour certaines raisons, certains doublons dans mon application Swift me causent des problèmes lors de la conversion à NSNumber, tandis que d'autres ne le sont pas. Mon application doit convertir les doublons avec 2 décimales (prix) en NSNumbers afin qu'ils puissent être stockés et récupérés en utilisant les données de base. Par exemple, quelques prix particuliers tels que 79,99 seraient évalués à 99,98999999999999 sauf si spécifiquement mis en forme en utilisant la méthode doubleValue de NSNumber.Conversion de Double à NSNumber dans Swift Perte Précision

Ici selectedWarranty.price = 79.99 comme le montre Débogueur

// item.price: NSNumber?  
// selectedWarranty.price: Double? 

item.price = NSNumber(double: selectedWarranty.price!) 

Je programmé des instructions d'impression pour montrer comment la conversion fonctionne

Original double: 79.99 
Converted to NSNumber: 79.98999999999999 
.doubleValue Representation: 79.99 

Quelqu'un peut-il expliquer s'il y a une raison pour laquelle la l'initialiseur ne peut sûrement pas garder 2 décimales pour chaque nombre? Je voudrais vraiment stocker les prix dans les données de base comme ils devraient l'être. Le formatage à chaque fois qu'il est affiché ne semble pas très pratique.

MISE À JOUR: converti objet de base de données au type NSDecimalNumber par modèle de données, 79,99 et 99,99 ne sont plus un problème, mais question maintenant plus facile à gérer avec des nombres différents ...

Original double: 39.99 
Converted to NSDecimalNumber: 39.99000000000001024 
+1

Pouvez-vous faire un [exemple minimal, complet et vérifiable] (http://stackoverflow.com/help/mcve)? – Alexander

+1

Utilisez NSDecimalNumber au lieu de NSNumber pour la devise. – rmaddy

+0

Je ne parviens pas à reproduire ce problème. http://swiftlang.ng.bluemix.net/#/repl/57bdc2590dcf4abf47da28c2 – Alexander

Répondre

9

Tout d'abord, vous re confondre quelques termes. 79.98999999999999 est une précision supérieure à 79.99 (il a une expansion décimale plus longue), mais une précision inférieure (il s'écarte de la valeur vraie).

Deuxièmement, NSNumber ne stocke ni 79.99 ni 79.98999999999999. Il stocke l'ampleur de la valeur selon la norme IEEE 754. Ce que vous voyez est probablement la conséquence de la logique d'impression appliquée pour convertir cette grandeur en un nombre lisible par l'homme. Dans tous les cas, vous ne devez pas compter sur Float ou Double pour stocker des valeurs avec une précision fixe. De par leur nature même, ils sacrifient la précision afin d'obtenir une plus grande gamme de valeurs représentables.

Vous seriez beaucoup mieux de représenter les prix comme Int de cents, ou comme NSDecimalNumber.

S'il vous plaît se référer à Why not use Double or Float to represent currency?

+0

Merci pour l'explication. Le chemin NSDecimalNumber semble le meilleur. Ma seule question est comment je peux obtenir le modèle de base de données pour me laisser utiliser cela au lieu de NSNumber? Je ne suis pas très expérimenté dans ce domaine – joelrorseth

+0

Je ne sais pas, essayez d'ouvrir une nouvelle question pour cela. Si vous pensez que cette réponse répond à votre question immédiate, veuillez la marquer comme acceptée :) – Alexander

1

Voilà comment doubles fonctionne partout. Si vous n'avez besoin que de deux décimales, pensez à utiliser integer/long au lieu d'ajouter un point après le deuxième chiffre, lorsque vous avez besoin d'afficher la valeur.