### Simple Scala puzzle

Who can guess what this tiny^{*} Scala program does?

object O extends App { val x = 123456789L val y = 0F val z = x - (if (true) x else y) println(z) }

(Apparently this mysterious snippet had been going around a while ago, but I only recently encountered a variation.)

Answer: Prints “−3.0”.

Why?

Short answer: The if/else causes `x`

to get promoted to Float, which rounds it up to 123456792.

Long answer after the fold.

The expression `(if (true) x else y)`

must have a type, and since Scala is statically typed, that type depends on the types of `x`

and `y`

only, without regard to the `if`

’s condition — `(if (false) x else y)`

would have the exact same type. That type is Float.

But why is it Float and not Long or Double? Why is the `if`

expression even interpreted to have a meaningful type when its `x`

and `y`

components don’t have matching types? That’s due to Scala’s implicit conversions. `scala.Predef`

contains a “`long2float`

” method that implicitly converts `x`

to `y`

’s type, and there’s no “`float2long`

” to compete with it, so `x`

is converted to Float by a call to `scala.Predef.long2float`

, and its output value is used as the value of the `if`

expression.

Fine, but why does that result in 123456789 turning into 123456792? That’s because single-precision floating point provides 24 bits (8 octal digits) for the significand^{†}, but 123456789 takes 27 bits to represent — it’s 111,0101,1011,1100,1101,0001,0101_{bin} and 726,746,425_{oct}. Rounding the 9-digit octal number to the 8 digits that fit in a Float^{‡} gives 726,746,430_{oct}, which is 123456792_{dec}. And that explains why it’s “−3”: 5_{oct} rounds up by 3 to 10_{oct}, and by rounding up instead of down it makes the difference from `x`

negative.

^{*} At just 115 characters, this could be twitcode #5 if demonstrating counterintuitive behavior qualifies as useful enough to count.

^{†} including the implicit leading bit

^{‡} The rounding in octal matches the rounding in binary because the high bit of the leading octal digit is set, so the leading *n* octal digits are exactly the leading 3*n* binary digits.