Strange Swift numbers type casting
I've just noticed that Swift does some type casting over Int and Double. When I try to evaluate
(10 / 3.0) - (10 / 3)
0.333...
is expected, but it's actually 0.0
.
Could someone explain this please?
Yes, I also found this quite surprising. Double
conforms to both FloatLiteralConvertible
and IntegerLiteralConvertible
(ExpressibleByFloatLiteral
and ExpressibleByIntegerLiteral
in Swift 3). Therefore a
Double
can be initialized with floating point literal
let a = 3.0
or with an integer literal:
let b : Double = 10
(The same is true for other floating point types like Float
and
CGFloat
.)
Now it might be unexpected for all of us with an (Objective-)C background that both statements
let x : Double = 10/4 // x = 2.5 . Really? Yes!
let y = 10/4 as Double // Same here ...
assign the value 0.25
to the variable. From the context, the result of the
division must be a Double
and Swift does not implicitly convert types.
Therefore /
must be the floating point division operator
func /(lhs: Double, rhs: Double) -> Double
so the compiler creates both arguments as Double
s from the literals
"10" and "4". (If 10/4
were treated as the division of two integers
then the result would also be an integer, and that cannot be assigned
to a Double
.)
Note that this is different from
let z = Double(10/4) // z = 2.0 . (I just thought that I understood it &%$!?)
which does an integer division and converts the result to Double
.
Double
has an init(_ v: Int)
constructor, and therefore 10/4
can be treated as the division of two integers here.
It really looks a bit strange if we summarize these results:
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
Now we can apply these results to your expression
(10 / 3.0) - (10 / 3)
The first part (10 / 3.0)
can only be a Double
, therefore -
must be the floating point subtraction operator
func -(lhs: Double, rhs: Double) -> Double
and thus (10 / 3)
must also be a Double
. Again, /
must be the floating point division operator, so 10
and 3
are treated as Double
constants.
Therefore the expression is equivalent to
(Double(10) / 3.0) - (Double(10) / Double(3))
and evaluates to 0.0
. If you change the expression to
(10 / 3.0) - Double(10 / 3)
then the result is 0.333...
because in this context, 10 / 3
is the division of two integer constants, as explained above.