Thursday, 27 August 2015

CFML: how should int() behave?

G'day:
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:

// testInt.java
public class TestInt {

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

Returns 37 when passed -37.357142857143.

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

JavaScript:
parseInt(-37.357142857143)
-37

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

Python:
>>> int(-37.357142857143)
-37

Clojure:
user=> (int -37.357142857143)
-37

Oops! Almost forgot PHP (I actually did forget... this is being added during a re-edit)
d:\webSites\www.scribble.local>php
<?php
$f = -37.357142857143;
$i = (int) $f;
echo $i;
^Z
-37

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?

--
Adam