首页 > 解决方案 > NumberFormatter 返回错误的数字

问题描述

我测试 NumberFormatter 以从 priceWithCurrency 获取数字。

如果价格大于 70 美元 NumberFormatter 转换错误的数字。

lazy var currencyFormatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.currencyCode = "USD"
        return formatter
}()


let price = "$71.9"

currencyFormatter.number(price)
//71.90000000000001

标签: swiftnumbersformatter

解决方案


如果你对 71.8 做同样的事情,它会起作用。这只是因为 71.9 不能用浮点数精确表示(由于位的有限性)

使用整数(以美分表示的价格)或小数是正确处理价格的唯一问题。检查DecimalNSDecimalNumber类,看看你能用它做什么。

如果您对价格进行一些计算,特别推荐,(如果您和两个朋友现金支付 10 美元,两个支付 3.33,一个支付 3.34 - 所以根据您的情况,除以 3 可能不够)

let number = currencyFormatter.number(from: price) ?? NSNumber(value: 0)
var value =  number.decimalValue
var roundedValue: Decimal = 0

// Right way: ( choose your precisions - 3 decimals here):
NSDecimalRound(&roundedValue, &value, 3, .bankers)

print(number)
print(value)
print(roundedValue)
71.90000000000001
71.90000000000001
71.9

如果您只需要记录您的价格,只需使用Int(price*100)/100 它就可以完成工作

如果你需要更多......祝你好运:)

编辑

继@Nicholas Rees 的精彩评论之后,我添加了这个变体:

currencyFormatter.generatesDecimalNumbers = true

let number = (currencyFormatter.number(from: price) as? NSDecimalNumber) ?? NSDecimalNumber(value: 0)
var value =  number.decimalValue
var roundedValue: Decimal = 0

// Right way: ( choose your precisions - 3 decimals here):
NSDecimalRound(&roundedValue, &value, 3, .bankers)

print(number)
print(value)
print(roundedValue)

在那里,记录时的结果相同,但我认为“值”的内部格式是正确的

另一种方法是删除货币并从字符串创建小数:

print(Decimal(string: "71.9") ?? 0)

71.9

推荐阅读