9

I am trying to convert a large number going in to Megabytes. I don't want decimals

numeric function formatMB(required numeric num) output="false" {
    return arguments.num \ 1024 \ 1024;
    } 

It then throws an error

enter image description here

How do I get around this?

James A Mohler
  • 11,060
  • 15
  • 46
  • 72
  • 9
    Any reason you cannot just use `/` (ie non integer divisor) and format to lop off the decimals? I suppose you could use PrecisionEvaluate() or BigInteger math, but that seems like overkill. – Leigh Feb 24 '16 at 05:10
  • 3
    @Leigh OMG! More than 3 years of CF experience and today I learnt about integer divisor and non integer divisor after reading your comment. I wonder how did I miss this. Thanks Leigh. – Tushar Bhaware Feb 24 '16 at 10:14
  • 1
    @TusharBhaware, my experience is 5 times yours and I still learn things from reading other people's answers on these forums. – Dan Bracuk Feb 24 '16 at 15:31
  • 2
    @TusharBhaware - Heh, that is what makes it fun :) Always something new to learn. – Leigh Feb 24 '16 at 16:57
  • @DanBracuk, Wow.. that is a huge experience. I hope to keep my hunger to know more alive as you did. – Tushar Bhaware Feb 25 '16 at 07:13
  • 2
    @Leigh, True. But I never thought I had to learn about operators after 3 years of programming. :) – Tushar Bhaware Feb 25 '16 at 07:18

2 Answers2

8

You can't change the size of a Long, which is what CF uses for integers. So you'll need to BigInteger instead:

numeric function formatMB(required numeric num) {
    var numberAsBigInteger = createObject("java", "java.math.BigInteger").init(javacast("string", num));
    var mbAsBytes = 1024 ^ 2;
    var mbAsBytesAsBigInteger = createObject("java", "java.math.BigInteger").init(javacast("string", mbAsBytes));
    var numberInMb = numberAsBigInteger.divide(mbAsBytesAsBigInteger);
    return numberInMb.longValue();
}

CLI.writeLn(formatMB(2147483648));

But as Leigh points out... for what you're doing, you're probably better off just doing this:

return floor(arguments.num / (1024 * 1024));
Adam Cameron
  • 29,677
  • 4
  • 37
  • 78
  • *the size of a Long* Small correction. The capacity of [`Integer`](http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html) is the limiting factor here. The capacity of a `Long` is much greater. [Trycf.com example](http://trycf.com/gist/f19684aa2d1a740751b0/acf2016?theme=monokai). – Leigh Feb 24 '16 at 19:23
3

the size of a Long, which is what CF uses for integers

Small correction for those that may not read the comments. CF primarily uses 32 bit signed Integers, not Long (which has a much greater capacity). So as the error message indicates, the size limit here is the capacity of an Integer:

  • Integer.MAX_VALUE = 2147483647
  • Long.MAX_VALUE = 9223372036854775807

It is worth noting that although CF is relatively typeless, some Math and Date functions also have the same limitation. For example, although DateAdd technically supports milliseconds, if you try and use a very large number:

//  getTime() - returns number of milliseconds since January 1, 1970 
currentDate = dateAdd("l", now().getTime(), createDate(1970,1,1));

... it will fail with the exact same error because the "number" parameter must be an integer. So take note if the documentation mentions an "Integer" is expected. It does not just mean a "number" or "numeric" ...

Leigh
  • 28,765
  • 10
  • 55
  • 103