使用小数类型处理货币输入时,我遇到精度问题。问题出在格式化程序上。这是游乐场中最小的可重现代码:
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.isLenient = true
formatter.maximumFractionDigits = 2
formatter.generatesDecimalNumbers = true
let text = "89806.9"
let decimal = formatter.number(from: text)?.decimalValue ?? .zero
let string = "\(decimal)"
print(string)
Run Code Online (Sandbox Code Playgroud)
它打印出来89806.89999999999而不是89806.9. 然而,大多数其他数字都很好(例如8980.9)。所以我不认为这是双精度与小数的问题。
编辑:
我需要使用格式化程序的原因是有时我需要处理货币格式输入:
let text = "$89,806.9"
let decimal = formatter.number(from: text)?.decimalValue ?? .zero
print("\(decimal)") // prints 89806.89999999999
let text2 = "$89,806.9"
let decimal2 = Decimal(string: text2)
print("\(decimal2)") // prints nil
Run Code Online (Sandbox Code Playgroud)
使用新的 FormatStyle 似乎会生成正确的结果
\nlet format = Decimal.FormatStyle\n .number\n .precision(.fractionLength(0...2))\n\n\nlet text = "89806.9"\nlet value = try! format.parseStrategy.parse(text)\nRun Code Online (Sandbox Code Playgroud)\n下面是使用区域设置中的货币代码解析货币的示例
\nlet currencyFormat = Decimal.FormatStyle.Currency\n .currency(code: Locale.current.currencyCode!)\n .precision(.fractionLength(0...2))\n\nlet amount = try! currencyFormat.parseStrategy.parse(text)\nRun Code Online (Sandbox Code Playgroud)\n瑞典语示例:
\nlet text = "89806,9 kr"\nprint(amount)\nRun Code Online (Sandbox Code Playgroud)\n\n\n89806.9
\n
另一种选择是使用 Decimal 的新 init,它采用 String 和 FormatStyle.Currency (或数字或百分比)
\nlet amount = try Decimal(text, format: currencyFormat)\nRun Code Online (Sandbox Code Playgroud)\n为了格式化这个值,我们可以使用formatted(_:)Decimal
print(amount.formatted(currencyFormat))\nRun Code Online (Sandbox Code Playgroud)\n输出(仍然是瑞典语):
\n\n\n89\xc2\xa0806,9\xc2\xa0kr
\n
| 归档时间: |
|
| 查看次数: |
1189 次 |
| 最近记录: |