NumberFormatter 在货币模式下对小负数的错误行为
Posted
技术标签:
【中文标题】NumberFormatter 在货币模式下对小负数的错误行为【英文标题】:NumberFormatter incorrect behaviour for small negative numbers in currency mode 【发布时间】:2019-04-11 10:34:29 【问题描述】:当使用 NumberFormatter
并将 numberStyle
设置为 .currency
时,格式化程序将所有数字四舍五入到小数点后 2 位,如预期的那样。但是,对于小负数,其值四舍五入到小数点后 2 位为 0(数字 >= -0.005),输出字符串包含负号,因此变为 -$0.00
而不是 $0.00
。
有没有办法通过切换NumberFormatter
的某些属性来改变这种行为,而不必使用解决方法?目前,我自己将值四舍五入到小数点后 2 位,检查输出是否为-0
并采取相应措施。但是,如果NumberFormatter
可以设置为不区分-0
和0
,那就太好了。
下面的代码显示了问题和我当前的解决方法(请随意在操场上进行测试) - 我知道 Locale
应该基于 currencySymbol
设置,但这只是展示问题的代码,而不是生产代码):
public class CurrencyFormatter
private let formatter: NumberFormatter
public init(locale: Locale = Locale.current)
let formatter = NumberFormatter()
formatter.locale = locale
formatter.numberStyle = .currency
self.formatter = formatter
// Adds currency symbol and returns a string e.g. input 1 output "£1"
public func formatWithCurrencySymbol(value: Decimal, currencyCode: String) -> String?
formatter.currencyCode = currencyCode
// Workaround for cases when the currency behaviour rounds small negative values (<0.0051) to -0.00, where we don't want to have a - sign
var value = value
if value < 0
let roundedValue = round(Double(truncating: value as NSDecimalNumber) * 100.0)
if roundedValue == 0 && roundedValue.sign == .minus
value = 0
return formatter.string(for: value)
public func formatWithCurrencySymbolNoWorkaround(value: Decimal, currencyCode: String) -> String?
formatter.currencyCode = currencyCode
return formatter.string(for: value)
let formatter = CurrencyFormatter()
formatter.formatWithCurrencySymbol(value: 0.01, currencyCode: "USD") // "$0.01"
formatter.formatWithCurrencySymbol(value: -0.001, currencyCode: "EUR") // "€0.00"
formatter.formatWithCurrencySymbol(value: -0.0002, currencyCode: "EUR") // "€0.00"
formatter.formatWithCurrencySymbol(value: -0.01, currencyCode: "EUR") // "-€0.01"
formatter.formatWithCurrencySymbol(value: 0.01, currencyCode: "USD") // "$0.01"
formatter.formatWithCurrencySymbol(value: -0.001, currencyCode: "EUR") // "-€0.00"
formatter.formatWithCurrencySymbol(value: -0.0002, currencyCode: "EUR") // "-€0.00"
formatter.formatWithCurrencySymbol(value: -0.01, currencyCode: "EUR") // "-€0.01"
formatter.formatWithCurrencySymbolNoWorkaround(value: -0.005, currencyCode: "EUR") // "-€0.00"
【问题讨论】:
相关:NSNumberFormatter rounding to negative zero @vacawama 谢谢,看来确实没有合适的配置解决方案 似乎没有,这很遗憾,因为许多人会发现负零是一个荒谬的显示。这让每个人都想出一个解决方法。 【参考方案1】:您可以添加简单的逻辑来检查该值是否小于 -0.01,如果是,则返回绝对值。
return value < -0.01 ? formatter.string(for: abs(value)) : formatter.string(for: value)
【讨论】:
正如您在问题中看到的那样,我在询问之前已经找到了解决方法,但我并不是在寻找解决方法,我正在寻找使用NumberFormatter
属性的适当解决方案来获取期望的行为(遗憾的是似乎不存在)。正如句子中所解释的那样:“有没有办法通过切换 NumberFormatter 的某些属性来改变这种行为,而不必使用解决方法?”
是的,很抱歉不得不使用完整的答案来传达我的想法。我会将此添加为评论,但我还没有足够的声誉点来直接评论。我只是提供了一个可能更简单的解决方法。如果 Apple 能够添加一个允许我们控制这种行为的属性,那就太好了。以上是关于NumberFormatter 在货币模式下对小负数的错误行为的主要内容,如果未能解决你的问题,请参考以下文章
Swift3:类型 numberformatter 没有成员“货币样式”,swift3