一尘不染

将NSNumber强制转换为Float时发生意外行为

swift

升级到Xcode
9.3(9E145)后,我的应用程序显示了一些意外行为。看来问题在于将NSNumber强制转换为Float。我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到Double的转换成功,对我而言,这毫无意义。

谁能向我解释这种行为?即是谁能给我一个很好的理由,说明为什么将n强制转换为Float?这是一个错误吗?如果这是预期的行为,那么您可以参考Swift文档中描述此位置的位置吗?


阅读 459

收藏
2020-07-07

共1个答案

一尘不染

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

as?for NSNumber应该表示“我可以安全地将存储在不透明框中的称为NSNumber的值表示为所需的值吗?”。

1.12是一个浮点文字,并推断为a 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位浮点值。

2020-07-07