Search code examples
swiftnumberformatter

NumberFormatter issue for large number


I try this code for converting string to number and vic versa. this code must print the same outputs. but its output is not correct. can any one help me?

let formatter: NumberFormatter = NumberFormatter()
formatter.locale = Locale(identifier: "en_US")


if let r1 = formatter.number(from: "10123456789012349") , let r2 = formatter.string(from:r1){

     print(r1) // output = 10123456789012349
     print(r2) // output = 10123456789012348
}

also this code has same problem

print(formatter.string(from:NSNumber(value: 10123456789012349)))
//output is 10123456789012348

Solution

  • NumberFormatter produces an Int64 when it parses the string in the example. This type can exactly represent the numeric value. But the formatter uses double arithmetic even for 64 bit integers to compute the string representation of a number. A double can represent approximately 16 or 17 decimal digits at most. This leads to the suprising different results.

    You can avoid this by using Decimals:

    let formatter: NumberFormatter = NumberFormatter()
    formatter.locale = Locale(identifier: "en_US")
    formatter.generatesDecimalNumbers = true
    
    let r1 = formatter.number(from: "10123456789012349")
    let r2 = formatter.string(from: r1!)
    print(r1!) // 10123456789012349
    print(r2!) // 10123456789012349
    

    EDIT: Using Decimals for formatting is sufficient for exact results:

    let formatter: NumberFormatter = NumberFormatter()
    formatter.locale = Locale(identifier: "en_US")
    let d1 = 10123456789012349 as Decimal
    
    print(formatter.string(from: d1 as NSNumber)!)