NSDecimalNumber 用于 Swift 中货币的精度

NSDecimalNumber usage for precision with currency in Swift

我读了很多书,认为 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

我在我的应用程序中使用核心数据。所以我坚持 NSDecimalNumber。除非我想将很多 NSDecimalNumbers 转换为 Decimals

有人可以帮我得到 0.07 吗?

问题是您正在有效地进行浮点数学运算(问题是它忠实地在 Double 中捕获小数小数值)并创建 Decimal(或 NSDecimalNumber) 来自已经引入此差异的 Double 值。相反,您想在进行除法之前创建 Decimal 值(或者在获得小数 Double 值之前,即使是文字)。

因此,以下内容等同于您的示例,它正在构建 0.07Double 表示(具有相应的限制),您最终得到的值不是恰好 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")

或指定 mantissa/significant 和指数:

let value = Decimal(sign: .plus, exponent: -2, significand: 7)  // or NSDecimalNumber(mantissa: 7, exponent: -2, isNegative: false)

最重要的是,在使用 Decimal(或 NSDecimalNumber)时完全避免使用 Double 表示,这样您就不会遇到您描述的问题。