奇怪的斯威夫特数字类型铸造

时间:2015-03-02 15:32:42

标签: swift casting type-inference

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

(10 / 3.0) - (10 / 3)
预计

0.333...,但实际上是0.0。 有人可以解释一下吗?

1 个答案:

答案 0 :(得分:16)

是的,我也觉得这很令人惊讶。 Double符合Swift 3中的FloatLiteralConvertibleIntegerLiteralConvertibleExpressibleByFloatLiteralExpressibleByIntegerLiteral。因此a 可以使用浮点字面值

初始化Double
let a = 3.0

或使用整数文字

let b : Double = 10

(对于Float和其他浮点类型也是如此 CGFloat。)

现在,我们所有人都有(目标 - )C背景可能会出乎意料 这两个陈述

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

将值0.25赋给变量。从上下文来看,结果是 除法必须是Double,Swift不会隐式转换类型。 因此/ 必须是浮点除法运算符

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

所以编译器从文字中创建两个参数Double “10”和“4”。 (如果将10/4视为两个整数的除法 那么结果也将是一个整数,并且无法分配 到Double。)

请注意,这与

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

执行整数除法并将结果转换为DoubleDouble有一个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

因此(10 / 3)也必须是Double。同样,/必须是浮点除法运算符,因此103被视为Double常量。

因此表达式等同于

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

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

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

然后结果为0.333...,因为在此上下文中10 / 3 是两个整数常量的除法,如上所述。