将 NSNumber 转换为浮点型时出现意外行为



升级到Xcode 9.3(9E145(后,我的应用程序出现了一些意外的行为。似乎问题出在将 NSNumber 转换为浮点数上。为此,我使用 as 类型转换运算符。请参阅以下示例。

let n = NSNumber.init(value: 1.12)
let m = NSNumber.init(value: 1.00)
let x = n as? Float
let y = m as? Float
let xd = n as? Double
let z = Float(truncating: n)

在这里,第一次强制转换失败,即 x == nil .第二个强制转换成功,并且使用 init:truncating 构造函数实例化 Float 也成功,即 z == 1.12 .n到双倍的演员阵容成功了,对我来说,这根本没有意义。

谁能向我解释这种行为? 即,谁能给我一个很好的理由,为什么 n 到 Float 的转换失败?这是一个错误吗?如果这是预期的行为,您能否参考 Swift 文档中描述此内容的位置?

这是 SE-0170 NSNumber 桥接和数值类型的结果,在 Swift 4 中实现:

NSNumber as?应该意味着"我是否可以安全地将存储在这个称为 NSNumber 的不透明框中的值表示为我想要的值?

1.12是一个浮点字面,并推断为Double,所以NSNumber(value: 1.12)是"装箱"64位浮点值最接近1.12 .将其转换为 32 位Float不会保留此值:

let n = NSNumber(value: 1.12)
let x = Float(truncating: n) // Or: let x = n.floatValue
let nn = NSNumber(value: x)
print(n == nn) // false

另一方面,1.0可以精确地表示为Float

let m = NSNumber(value: 1.0)
let y = m.floatValue
let mm = NSNumber(value: y)
print(m == mm) // true

这就是铸造m as? Float成功的原因。双

n.floatValue
Float(truncating: n)

可用于将数字"截断"为最接近的可表示值32 位浮点值。

最新更新