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?
source to share
It seems to be a mistake, compare
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
}
source to share