I’ve developed a custom control for money input, which contains UITextField
and UILabel
. When the user taps on it, it becomes active and switches to the UITextField
for data input and accepts only numbers and dot symbol, when the user finishes editing it becomes passive and switches to UILabel
just to show formatted money value. But there is one little issue which I’m unable to fix a lot of days already.
Let’s say the user writes down 88.99
and presses done, this becomes "$ 88.99"
in a UILabel
, next when the user again taps on it to edit the initial value I get the following value "88.98999999999999"
. To not present the entire code I selected the core part in a playground format which gives the same result as in my complete project:
extension NumberFormatter {
static public func defaultCurrencyFormatter() -> NumberFormatter {
let formatter = NumberFormatter()
formatter.usesGroupingSeparator = true
formatter.numberStyle = .currency
formatter.currencySymbol = ""
formatter.minimumFractionDigits = 1
formatter.maximumFractionDigits = 2
formatter.currencyGroupingSeparator = ","
formatter.currencyDecimalSeparator = "."
return formatter
}
}
let stringValue = NumberFormatter.defaultCurrencyFormatter().number(from: "88.99")?.stringValue
print(stringValue) // result is Optional("88.98999999999999")
I have no idea why using this NumberFormatter I get such a result. I was thinking that explicitly setting minimumFractionDigits
and maximumFractionDigits
will solve my issue but it does not affect my result
2
Answers
NumberFormatter
is legacy from objc and it operates withNSNumber
/CGFloat
etc. and usually it is helpful for localized text formatting. Much powerful and convenient parser for numbers isScanner
but if you don’t have complex data structure to parse and don’t want to deal withFloating-point error mitigation
just use swift’sFloat
:Try this:
to use it: