将NSNumber强制转换为Float时发生意外行为 [英] Unexpected behavior when casting an NSNumber to 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?
forNSNumber
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屋!