Thursday, 27 August 2015

CFML: how should int() behave?

One of the scintillating conversations on the CFML Slack channel today was regarding people's expectations of CFML's int() function. Ross had this expression:

int(35 - (1013 / (13+1)))

And he quite legitimately expected the result to be -37 (the float value before converting to an int is -37.357142857143). However because CFML is daft (IMO), its integer conversion follows this rule:
Calculates the closest integer that is smaller than number.
Which means the result of the expression is -38.

What it should do is simply return the integer part of the number. It's not a rounding function, it's a conversion function.

I thought there might be a precedent in other languages, but here's some code samples:

public class TestInt {

    public static int toInt(Double f){
        return f.intValue();

Returns 37 when passed -37.357142857143.

irb(main):004:0> -37.357142857143.to_i
=> -37


groovy:000> (int) -37.357142857143
===> -37

>>> int(-37.357142857143)

user=> (int -37.357142857143)

Oops! Almost forgot PHP (I actually did forget... this is being added during a re-edit)
$f = -37.357142857143;
$i = (int) $f;
echo $i;

You get the idea.

So... it's a bit late in the game to fix int() in CFML, but John Whish has raised a ticket for ColdFusion: "Deprecate `int` in favour of `floor`" (4044533). This makes good sense to me. CFML already has a ceiling() function, so it makes sense to also have floor().

Note one can use fix() in CFML to get the right result, ie: just the integer part of the number. But that's just a fix. Pity int() didn't just do the right thing in the first place.

Is there any precedent in any other language for an int() operation to actually do rounding instead?