ios - 将 NSNumber 转换为 Float 时出现意外行为

标签 ios swift swift4

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

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

最佳答案

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

as? for NSNumber should mean "Can I safely express the value stored in this opaque box called a NSNumber as the value I want?".

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 转换为? float 成功。两者皆有

n.floatValue
Float(truncating: n)

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

关于ios - 将 NSNumber 转换为 Float 时出现意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57208635/

相关文章:

php - 防止请求超时 - 大 POST 数据

ios - 如何在 iOS 中使用平衡支付将 href 发送到服务器进行支付处理

ios - 快速访问 UIButton 的文本时出现奇怪的错误

swift - 编译器错误 : Method with Objective-C selector conflicts with previous declaration with the same Objective-C selector

ios - 如何替换或解决 unistd.h 中的 __TVOS_PROHIBITED 依赖项

ios - tableView.hidden 破坏其他元素

ios - 新的 Fabric Crashlytics 设置具有多种 iOS 配置,无 dSYM

ios - 更新子字符串(到 :) results in generic parameter could not be inferred

ios - 如何检测用户何时从应用程序中截取屏幕截图?

iphone - for 循环随机卡在 executeFetchRequest :error: