【问题标题】:Unexpected behavior when casting an NSNumber to Float将 NSNumber 转换为 Float 时出现意外行为
【发布时间】:2018-04-06 08:53:21
【问题描述】:

升级到 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 转换为 Double 成功,对我来说,这根本没有意义。

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

【问题讨论】:

  • 为什么要使用 as 进行类型转换?为什么不使用 NSNumber 的 floatValue & doubleValue 方法??
  • @rishi : 在我的应用程序中我使用的是 as?运算符,因为要转换的值实际上是 Any?由网络服务(firebase)返回。 Firebase 使用 NSNumber 来表示数值。

标签: ios swift swift4


【解决方案1】:

这是SE-0170 NSNumber bridging and Numeric types 的结果,在 Swift 4 中实现:

as? for NSNumber 应该表示“我可以安全地将存储在这个称为 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 位浮点值。

【讨论】:

  • 如何将[NSArray] 转换为[[Float]]?我必须先转换为 Double 并在 for 循环中使用 Float 初始化程序还是有更简单的解决方案?
猜你喜欢
  • 2019-11-16
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多