将NSNumber强制转换为Float时发生意外行为 [英] Unexpected behavior when casting an NSNumber to Float

查看:164
本文介绍了将NSNumber强制转换为Float时发生意外行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

升级到Xcode 9.3(9E145)后,我的应用程序显示了一些意外行为.似乎问题在于将NSNumber强制转换为Float.我为此使用as类型强制转换运算符.请参见以下示例.

After upgrading to Xcode 9.3 (9E145) my App showed some unexpected behavior. It seems that the issue is with a cast of an NSNumber to a Float. I use the as type cast operator for this. See the following example.

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可以成功,对我而言,这根本没有任何意义.

Here, the first cast fails, i.e. x == nil. The second cast succeeds and the instantiation of a Float with the init:truncating constructor also succeeds, i.e. z == 1.12. The cast of n to a Double succeeds, which, to me, makes no sense at all.

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

Can anyone explain this behavior to me? I.e. can anyone give me a good reason why the cast of n to a Float fails? Is this a bug? If this is intended behavior, can you please reference the location in the Swift documentation that describes this?

推荐答案

这是

This is a consequence of SE-0170 NSNumber bridging and Numeric types, implemented in Swift 4:

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

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 保留此值:

1.12 is a floating point literal, and inferred as a Double, so NSNumber(value: 1.12) is "boxing" the 64-bit floating point value closest to 1.12. Converting that to a 32-bit Float does not preserve this value:

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:

On the other hand, 1.0 can be represented exactly as a Float:

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

,这就是铸造m as? Float成功的原因.两者

and that is why casting m as? Float succeeds. Both

n.floatValue
Float(truncating: n)

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

can be used to "truncate" the number to the closest representable 32-bit floating point value.

这篇关于将NSNumber强制转换为Float时发生意外行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆