NSDecimalNumber 用于 Swift 中的货币精度 [重复]
Posted
技术标签:
【中文标题】NSDecimalNumber 用于 Swift 中的货币精度 [重复]【英文标题】:NSDecimalNumber usage for precision with currency in Swift [duplicate] 【发布时间】:2018-02-05 23:09:19 【问题描述】:我读过很多,NSDecimalNumber
是使用货币时使用的最佳格式。
但是,我仍然遇到浮点问题。
例如。
let a: NSDecimalNumber = 0.07 //0.07000000000000003
let b: NSDecimalNumber = 7.dividing(by: 100) //0.06999999999999999
我知道我可以使用 Decimal
并且 b 就是我所期望的:
let b: Decimal = 7 / 100 //0.07
我在我的应用程序中使用 Core Data。所以我坚持使用NSDecimalNumber
。除非我想将很多 NSDecimalNumbers
转换为 Decimals
。
有人可以帮我弄到 0.07 吗?
【问题讨论】:
在向用户显示货币数据时,您应该使用NumberFormatter
。
只需使用 NumberFormatter 来显示您的号码。顺便说一句 0.06999999999999999 和 0.07 它实际上是相同的数字。顺便说一句,我会使用 Decimal 并在需要时将其转换为 NSDecimalNumber
问题是您分配的0.07
本身就是Double
,它在NSDecimalNumber
发挥作用之前引入了精度问题。如果你想要0.07
的无损表示,你需要使用NSDecimalNumber
初始化器,它接受一个字符串"0.07"
比较***.com/questions/42781785/…
@Rob:没有必要道歉或解释自己——我不会想到别的。
【参考方案1】:
问题在于您正在有效地进行浮点数学运算(存在忠实捕获Double
中的小数部分值的问题)并从Double
值创建Decimal
(或NSDecimalNumber
)已经引入了这种差异。相反,您希望在进行除法之前创建您的 Decimal
值(或者在获得小数 Double
值之前,即使是文字)。
因此,以下内容与您的示例等效,它正在构建0.07
的Double
表示(具有必然的限制),并且您最终得到的值不完全是0.07
:
let value = Decimal(7.0 / 100.0) // or NSDecimalNumber(value: 7.0 / 100.0)
而这不会遇到这个问题,因为我们将小数 7
除以小数 100
:
let value = Decimal(7) / Decimal(100) // or NSDecimalNumber(value: 7).dividing(by: 100)
或者,在过程中创建0.07
值但避免Double
的其他方法包括使用字符串:
let value = Decimal(string: "0.07") // or NSDecimalNumber(string: "0.07")
或指定尾数/有效数和指数:
let value = Decimal(sign: .plus, exponent: -2, significand: 7) // or NSDecimalNumber(mantissa: 7, exponent: -2, isNegative: false)
最重要的是,在使用Decimal
(或NSDecimalNumber
)时完全避免Double
表示,并且您不会遇到您描述的问题。
【讨论】:
说得真好。非常感谢!这对我很有帮助。Decimal(7)
适用于像 7 这样的简单数字,但更准确的方法是使用 NSNumber(floatLiteral: 7).decimalValue
。我使用Decimal
进行金融交易,在某些情况下,Decimal(7)
之类的方法不会产生准确的货币结果。虽然这种差异很小,但在金融交易中会加起来。
我建议也小心NSNumber(floatLiteral: x).decimalValue
模式,因为这需要x
,伴随任何浮点问题,并且简单地捕获这些问题。作为一般规则,我仍然建议在使用非整数值时,使用上述模式之一。以上是关于NSDecimalNumber 用于 Swift 中的货币精度 [重复]的主要内容,如果未能解决你的问题,请参考以下文章