奇怪的 Swift 数字类型转换

Strange Swift numbers type casting

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

(10 / 3.0) - (10 / 3)

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

是的,我也觉得很意外。 Double 符合 FloatLiteralConvertibleIntegerLiteralConvertibleExpressibleByFloatLiteralExpressibleByIntegerLiteral in Swift 3)。因此一个 Double可以用浮点字面量

初始化
let a = 3.0

或使用 整数文字:

let b : Double = 10

(其他浮点类型如 FloatCGFloat.)

现在对于我们所有具有 (Objective-)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

所以编译器从字面量中将两个参数创建为 Doubles “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 是两个整数常量的除法,如上所述。