swift - 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
解决方案
如果你对 71.8 做同样的事情,它会起作用。这只是因为 71.9 不能用浮点数精确表示(由于位的有限性)
使用整数(以美分表示的价格)或小数是正确处理价格的唯一问题。检查Decimal
和NSDecimalNumber
类,看看你能用它做什么。
如果您对价格进行一些计算,特别推荐,(如果您和两个朋友现金支付 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
推荐阅读
- laravel - Laravel 5.4 - Access Static Method inside Controller Method
- javascript - 如何在 HTML 中打印 javascript 函数结果
- excel - 如何让 Autohotkey 写入元数据,然后提取该元数据以用于重命名文件
- reporting-services - 在 SSRS 报告中显示表格中的数据
- python - 在定义函数的文件中修补函数
- azure-functions - Azure Function App CosmosDbTrigger Gives Null Parameter Error
- amazon-web-services - 使用 CloudFormation 有条件地定义 Elastic Beanstalk 环境变量
- database - 为用户构建隐私设置
- django - 将类实例传递给 Django 中的会话
- php - 如何使用 PHP 找出我的服务器的请求 IP