Actionscript 3: Faster Math.floor and Math.ceil using int typecast
Please note that this post is over a year old and may contain outdated information.
In order to use int typecasting in place of Math.floor or Math.ceil, you must first understand exactly what these functions do: Math.floor takes a number and returns the next lowest whole integer. Passing 0.9 will return 0 and -0.9 will return -1. Math.ceil returns the next highest integer, so will return 1 from 0.9 and 0 from -0.9. This is different than truncating, which would return 0 in all cases, and is why typecasting using int (usually used to truncate) wouldn't seem to work at first.
In order to make int typecasting work, you need to add a condition check to see if the number is negative or positive (negative for floor, positive for ceil), and adjust it by 1 if it is. Why do this instead of just using Math.floor or Math.ceil? Because it is faster and you can avoid a function call if desired. Look at these examples:
Using Math.floor like normal requires 691 milliseconds for this run:
Now using a custom floor function:
The above took 601 milliseconds to process. Now you may wonder if the savings are worth the effort of having the extra function, and in some cases I would say no. But that's not where the real performance advantage is to be had. By using int typecasting and the condition, you can avoid the use of a function altogether, and do something like this:
The above only took 113 milliseconds to process.
Here is the code for finding the ceiling:
Notice that I checked to see if the original number is greater than 0, and if so added 1.
In order to make int typecasting work, you need to add a condition check to see if the number is negative or positive (negative for floor, positive for ceil), and adjust it by 1 if it is. Why do this instead of just using Math.floor or Math.ceil? Because it is faster and you can avoid a function call if desired. Look at these examples:
Using Math.floor like normal requires 691 milliseconds for this run:
var i:int = 0;
var testVar:Number = -82.20035;
var floored:Number;
var time1 = new Date();
for(i = 0; i < 5000000; i ++)
{
floored = Math.floor(testVar);
}
var time2 = new Date();
trace(time2 - time1);
Now using a custom floor function:
var i:int = 0;
var testVar:Number = 82.20035;
var floored:Number;
var time1 = new Date();
for(i = 0; i < 5000000; i ++)
{
floored = floor(testVar)
}
var time2 = new Date();
trace(time2 - time1);
function floor(n:Number):Number
{
if(n < 0) n-= 1;
return int(n);
}
The above took 601 milliseconds to process. Now you may wonder if the savings are worth the effort of having the extra function, and in some cases I would say no. But that's not where the real performance advantage is to be had. By using int typecasting and the condition, you can avoid the use of a function altogether, and do something like this:
var i:int = 0;
var testVar:Number = 82.20035;
var floored:Number;
var time1 = new Date();
for(i = 0; i < 5000000; i ++)
{
if(testVar < 0) floored = int(testVar - 1)
else floored = int(testVar);
}
var time2 = new Date();
trace(time2 - time1);
The above only took 113 milliseconds to process.
Here is the code for finding the ceiling:
if(testVar > 0) ceiling = int(testVar + 1)
else ceiling = int(testVar);
Notice that I checked to see if the original number is greater than 0, and if so added 1.