Swiftyjson: Incorrect parsing of 8.7 value

Created on 17 Jan 2018  路  1Comment  路  Source: SwiftyJSON/SwiftyJSON

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)

Environment

List the software versions you're using:

  • SwiftyJSON: 4.0.0
  • Xcode Version: 9.2
  • Swift Version: 4

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 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.

>All comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ejpusa picture ejpusa  路  5Comments

Xorcist77 picture Xorcist77  路  4Comments

Causaelity picture Causaelity  路  5Comments

MrLoveQD picture MrLoveQD  路  5Comments

amit-bhavsar picture amit-bhavsar  路  5Comments