sample code:
let json: JSON = JSON(["number": 8.7])
let num = json["number"]
print(num.stringValue)
print(num.numberValue)
print(num.number)
print(num.double)
expected to get 8.7 value
instead get:
8.699999999999999
8.699999999999999
Optional(8.699999999999999)
Optional(8.6999999999999993)
List the software versions you're using:
This is normal. The printer cannot accurately print decimal numbers. What you are seeing is the _floating point representation_ of an input decimal number, and computers cannot correctly represent all decimal numbers in floating point.
You should instead print a string computed by NumberFormatter, configured with a numberStyle set to .decimal. You will then see the correct value:
let json: JSON = JSON(["number": 8.7])
let num = json["number"].numberValue
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
let stringOutput = formatter.string(from: num)!
print("\(stringOutput)")
Output: 8.7
NOTE: The console printer does not use NumberFormatter, so even printing an NSNumber will simply call the receiver's doubleValue, leaving you with the conversion error you are encountering.
Whenever you require parsing, processing, and display of decimal numbers, you should wrap them in NSDecimalNumber or Decimal (Swift's bridge to NSDecimalNumber).
In your input JSON, keep these numbers as strings (don't even put a Double _into_ the dictionary!), and then parse them to Decimal directly with an initialiser:
let json: JSON = JSON(["number": "8.7"])
let numberAsString = json["number"].stringValue
let numberAsDecmal = Decimal(string: numberAsString)
You can then do arithmetic using conventional operators like +, -, *, / etc.
Then, if you require the output printed or displayed on-screen, is _must_ go back through the NumberFormatter. The formatter only takes NSNumber or NSDecimalNumber, but since the latter is bridged, you can simply cast it: numberAsDecimal as NSDecimalNumber.
Never use Double for any currency related operations.
Most helpful comment
This is normal. The printer cannot accurately print decimal numbers. What you are seeing is the _floating point representation_ of an input decimal number, and computers cannot correctly represent all decimal numbers in floating point.
You should instead print a string computed by
NumberFormatter, configured with anumberStyleset to.decimal. You will then see the correct value:Output:
8.7NOTE: The console printer does not use
NumberFormatter, so even printing anNSNumberwill simply call the receiver'sdoubleValue, leaving you with the conversion error you are encountering.Whenever you require parsing, processing, and display of decimal numbers, you should wrap them in
NSDecimalNumberorDecimal(Swift's bridge to NSDecimalNumber).In your input JSON, keep these numbers as strings (don't even put a
Double_into_ the dictionary!), and then parse them toDecimaldirectly with an initialiser:You can then do arithmetic using conventional operators like
+, -, *, /etc.Then, if you require the output printed or displayed on-screen, is _must_ go back through the
NumberFormatter. The formatter only takes NSNumber or NSDecimalNumber, but since the latter is bridged, you can simply cast it:numberAsDecimal as NSDecimalNumber.Never use
Doublefor any currency related operations.