Generates DecimalNumbers for NumberFormatter doesn't work

My function converts the string to decimal

func getDecimalFromString(_ strValue: String) -> NSDecimalNumber {
    let formatter = NumberFormatter()
    formatter.maximumFractionDigits = 1
    formatter.generatesDecimalNumbers = true
    return formatter.number(from: strValue) as? NSDecimalNumber ?? 0
}

      

But it doesn't work on hold. Sometimes it comes back like

Optional(8.300000000000001)
Optional(8.199999999999999)

      

instead of 8.3 or 8.2. In the string, the value is either "8.3" or "8.2", but the converted decimal value does not meet my requirements. Any suggestion where did I go wrong?

+3
decimal numbers swift


source to share


1 answer


It seems to be a mistake, compare

  • NSDecimalNumber

    from NSNumberFormatter

    are prone to binary approximation error

Even if generatesDecimalNumbers

set to true

, the formatter generates a binary floating point number internally, and it cannot represent decimals such as 8.2

exactly.

Note that (unlike the documentation) the property maximumFractionDigits

has no effect when parsing a string to a number.

There is a simple solution: use

NSDecimalNumber(string: strValue) // or
NSDecimalNumber(string: strValue, locale: Locale.current)

      



depending on whether the string is localized or not.

Or with Swift 3 type Decimal

:

Decimal(string: strValue) // or
Decimal(string: strValue, locale: .current)

      

Example:

if let d = Decimal(string: "8.2") {
    print(d) // 8.2
}

      

+4


source to share







All Articles
Loading...
X
Show
Funny
Dev
Pics