joelrorseth - 1 year ago 414
Swift Question

Converting Double to NSNumber in Swift Loses Accuracy

For some reason, certain Doubles in my Swift app are giving me trouble when converting to NSNumber, while some are not. My app needs to convert doubles with 2 decimal places (prices) to NSNumbers so they can be stored and retrieved using Core Data. For example, a few particular prices such as 79.99 would evaluate to 99.98999999999999 unless specifically formatted using NSNumber's doubleValue method.

Here selectedWarranty.price = 79.99 as shown in debugger

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

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

I programmed some print statements to show how the conversion works out

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

Can somebody explain if there is a reason why the initializer cannot surely keep 2 decimal places for every number? I would really like to store the prices in Core Data like they should be. Formatting every time it is displayed doesn't sound very convenient.

Firstly, you're confusing some terms. `79.98999999999999` is higher precision than `79.99` (it has a longer decimal expansion), but lower accuracy (it deviates from the true value).
Secondly, NSNumber does not store neither `79.99` nor `79.98999999999999`. It stores the magnitude of the value according to the `IEEE 754` standard. What you're seeing is likely the consequence of the printing logic that's applied to convert that magnitude into a human readable number. In any case, you should not be relying on `Float` or `Double` to store values with a fixed precision. By their very nature, they sacrifice precision in order to gain a longer range of representable values.
You would be much better off representing prices as an `Int` of cents, or as an `NSDecimalNumber`.