为什么Swift .intValue返回错误/奇怪的值?

时间:2020-05-05 15:51:59

标签: ios swift xcode decimal nsdecimalnumber

我正在尝试转换代表美元金额的十进制数。然后,将其转换为NSDecimalNumber以应用.intValue转换。

但是我的行为很奇怪。首先,当将该值乘以100时,它将给我一个不精确的值。当应用.intValue时,我得到一个完全意外的数字。感谢您的帮助!

//Issue
let dollars: Decimal = 106.99 * 100 // 10698.999999999997952
let cast = dollars as NSDecimalNumber // 10699
let int = cast.intValue //-7747


//No Problems here
let dollars2: Decimal = 106.98 * 100 // 10698
let cast2 = dollars2 as NSDecimalNumber // 10698
let int2 = cast2.intValue //10698

2 个答案:

答案 0 :(得分:2)

您也可以尝试执行此操作

let dollars = "\(106.99 * 100)"
let cast = NSDecimalNumber(string: dollars)
let int = cast.intValue

答案 1 :(得分:0)

Decimal's FloatLiteralType is Double

麻烦的是,106.99不能用Double表示。只是将其弹出到Decimal中是有问题的:

Decimal(106.99) == 106.98999999999997952 // true
106.99 as Decimal * 100 // 10698.999999999997952

因此,您必须对Double进行消毒。

extension Decimal {
  init(dollarsAndCents: Double) {
    self = Self( (dollarsAndCents * 100).rounded() ) / 100
  }
}
extension Decimal {
  var dollarsAndCents: (dollars: Int, cents: Int) {
    (self * 100 as NSDecimalNumber).intValue
    .quotientAndRemainder(dividingBy: 100) as (Int, Int)
  }
}
Decimal(dollarsAndCents: 106.99).dollarsAndCents // (dollars: 106, cents: 99)

这在实践中很好,因为Decimal是为了钱。进行消毒,您永远不会遇到错误。