奇怪的Swift数字类型铸造



我刚刚注意到Swift对Int和Double进行了一些类型转换。当我尝试评估时

(10 / 3.0) - (10 / 3)

应为0.333...,但实际上是0.0。有人能解释一下吗?

是的,我也觉得这很令人惊讶。CCD_ 3同时符合FloatLiteralConvertibleIntegerLiteralConvertible(Swift 3中的ExpressibleByFloatLiteralExpressibleByIntegerLiteral)。因此Double可以用浮点文字初始化

let a = 3.0

或带有整数文字

let b : Double = 10

(其他浮点类型也是如此,如FloatCGFloat.)

现在,对于我们所有拥有(目标-)C背景的人来说,这可能是出乎意料的两份声明

let x : Double = 10/4     // x = 2.5 .  Really? Yes!
let y = 10/4 as Double    // Same here ...

将值CCD_ 11分配给变量。从上下文来看division必须是Double,并且Swift不会隐式转换类型。因此/必须为浮点除法算子

func /(lhs: Double, rhs: Double) -> Double

因此编译器从文字中创建两个参数作为Double"10"one_answers"4"。(如果10/4被视为两个整数的除法那么结果也是一个整数,不能赋值到CCD_ 16。)

请注意,这与不同

let z = Double(10/4)   // z = 2.0 . (I just thought that I understood it &%$!?)

其进行整数除法并将结果转换为CCD_ 17。Double有一个init(_ v: Int)构造函数,因此10/4可以将视为两个整数的除法。

如果我们总结这些结果,这看起来确实有点奇怪:

let x : Double = 10/4     // x = 2.5 
let y = 10/4 as Double    // y = 2.5
let z = Double(10/4)      // z = 2.0

现在我们可以将这些结果应用于您的表达式

(10 / 3.0) - (10 / 3)

第一部分(10 / 3.0)只能是Double,因此-必须是浮点减法运算符

func -(lhs: Double, rhs: Double) -> Double

因此CCD_ 24也必须是CCD_。同样,/必须是浮点除法运算符,因此103被视为Double常数。

因此,该表达式等效于

(Double(10) / 3.0) - (Double(10) / Double(3))

并评估为CCD_ 30。如果将表达式更改为

(10 / 3.0) - Double(10 / 3)

则结果是Double1,因为在这种情况下,10 / 3是两个整数常数的除法,如上所述。

最新更新